function varargout = exp_bruce2018(varargin)
%EXP_BRUCE2018 Experiments from Bruce et al. 2018
%
%   exp_bruce2011(fig) reproduce Fig. no. fig from the Bruce et
%   al. 2018 paper.
%
%   The following flags can be specified;
%
%     'fig7b'    Reproduce Fig. 7 panel b.
%
%     'fig8b'    Reproduce Fig. 8, panel b.
%
%     'fig10'    Reproduce Fig. 10.
%
%
%   Examples:
%   ---------
%
%   To display Fig. 7b use :
%
%     exp_bruce2018('fig7b');
%
%   To display Fig. 8b use :
%
%     exp_bruce2018('fig8b');
%
%   To display Fig. 10 use :
%
%     exp_bruce2018('fig10');
%
%   AUTHOR: Ian Bruce
%
%   Url: http://amtoolbox.sourceforge.net/amt-0.10.0/doc/experiments/exp_bruce2018.php

% Copyright (C) 2009-2020 Piotr Majdak and the AMT team.
% This file is part of Auditory Modeling Toolbox (AMT) version 1.0.0
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

  
definput.import={'amt_cache'};
definput.flags.type={'missingflag', ...
    'fig7b', ... % 'popratelevel'
    'fig8b', ... % 'fanofactor'
    'fig10'}; 

definput.flags.plot={'plot','no_plot'};

flags  = ltfatarghelper({},definput,varargin);

if flags.do_missingflag
  flagnames=[sprintf('%s, ',definput.flags.type{2:end-2}),...
             sprintf('%s or %s',definput.flags.type{end-1},definput.flags.type{end})];
  error('%s: You must specify one of the following flags: %s.',upper(mfilename),flagnames);
end;


%%% Common parameters:
Fs = 100e3;    % sampling rate in Hz (must be 100, 200 or 500 kHz)
dt=1/Fs; %  each time in length

%% demo_bruce2018_popratelevel.m
if flags.do_fig7b
    
    numcfs = 1;
    CFs   = 8e3;  % CF in Hz;

    numsponts = [1 1 3]; % reduce the number of ANFs to have a shorter simulation time
    %numsponts = [20 20 60];
    stimdbs = -10:5:100;
    
    numstims = length(stimdbs);
    rates = zeros(numcfs,sum(numsponts),numstims);

    cohc  = 1.0;   % normal ohc function
    cihc  = 1.0;   % normal ihc function
    species = 'cat';   % cat or human
    implnt = 'approxPL';    % 'approxPL', or'actualPL'
    noiseType = 'varFGn'; % 'fixedFGn', or'varFGn'
    
    % stimulus parameters
    T  = 50e-3;  % stimulus duration in seconds
    rt = 2.5e-3; % rise/fall time in seconds

    % PSTH parameters
    psthbinwidth = 0.5e-3; % binwidth in seconds;
    nrep = 100;  % number of stimulus repetitions - Liberman (1978) used 10;

    t = 0:dt:T-dt; % time vector
    mxpts = length(t);
    irpts = rt*Fs;
    
    pin = sqrt(2)*sin(2*pi*CFs*t); % unramped stimulus
    pin(1:irpts) = pin(1:irpts).*(0:(irpts-1))/irpts;
    pin((mxpts-irpts):mxpts) = pin((mxpts-irpts):mxpts).*(irpts:-1:0)/irpts;
    
    figure
    for ii = 1:numstims
       pin=scaletodbspl(pin,stimdbs(ii));
       output = bruce2018(pin, round(1/dt), CFs, 'nrep', nrep, ...
           'numL', numsponts(1), 'numM',numsponts(2) , 'numH',numsponts(3) ,...
           'psthbinwidth_mr', psthbinwidth, 'reptime', 2, ...
           noiseType, implnt, 'cohcs', cohc, 'cihcs', cihc, species, 'outputPerSynapse');
    
       psth = output.psth_ft;
                
       psthbins = round(psthbinwidth*Fs);  % number of psth bins per psth bin
       pr = zeros(size(psth, 3), length(psth)/psthbins);
       psTH = zeros(size(pr));
       
       ronset = round(1.5e-3/psthbinwidth)+1;
       roffset = round(T/psthbinwidth);
    
       for jj = 1: size(psth, 3)
         % pr of spike in each bin
         pr(jj,:) = sum(reshape(psth(:,:,jj),psthbins,length(psth)/psthbins))/nrep; 
         psTH(jj,:) = pr(jj,:)/psthbinwidth; % psth in units of /s
         rates(1,jj, ii)= mean(psTH(jj,ronset:ronset+roffset));
       end
    end

 for spontlp = 1:sum(numsponts)
    if (spontlp<=numsponts(1))
      plot(stimdbs,squeeze(rates(1,spontlp,:)),'r')
      hold on
    elseif (spontlp<=sum(numsponts([1 2])))
      plot(stimdbs,squeeze(rates(1,spontlp,:)),'b')
      hold on
    else
      plot(stimdbs,squeeze(rates(1,spontlp,:)),'m')
      hold on
    end
 end
    xlabel('Stimulus Level (dB SPL)')
    ylabel('Firing Rate (/s)')
end    

%% demo_bruce2018_fanofactor.m
if flags.do_fig8b
    
    % model fiber parameters

    %default nerve fiber parameters of the models, therefore not explicitly
    %passed to bruce2018
    spont = 50;      % spontaneous firing rate
    tabs   = 0.6e-3; % absolute refractory period
    trel   = 0.6e-3; % baseline mean relative refractory period
    CF    = 1.5e3;   % CF in Hz;
    cohc  = 1.0;     % normal ohc function
    cihc  = 1.0;     % normal ihc function
    species = 'cat';     % cat or human (with Shera et al. tuning)
    noiseType = 'varFGn';   % variable fGn; for fixed (frozen) fGn: 'fixedFGn'
    implnt = 'approxPL';      % approximate 
                              %for actual implementation of the power-law functions in the Synapse: 'actualPL'

    % stimulus parameters
    F0 = CF;     % stimulus frequency in Hz
    T  = 25;  % stimulus duration in seconds
    rt = 2.5e-3; % rise/fall time in seconds

    stimdb = -inf; % stimulus intensity in dB SPL; set to -inf to get spont activity

    trials = 10;

    numTs = 14;
    Ts = logspace(log10(1e-3),log10(10),numTs);
    Ts = round(Ts/dt)*dt;

    Ft = zeros(trials,numTs);
    Ft_shuf = zeros(trials,numTs);
    meanrate = zeros(trials,numTs);

    % PSTH parameters

    nrep = 1;               % number of stimulus repetitions (e.g., 50);
    t = 0:1/Fs:T-1/Fs; % time vector
    mxpts = length(t);
    irpts = rt*Fs;

    pin = sqrt(2)*20e-6*10^(stimdb/20)*sin(2*pi*F0*t); % unramped stimulus
    pin(1:irpts)= pin(1:irpts).*(0:(irpts-1))/irpts;
    pin((mxpts-irpts):mxpts)=pin((mxpts-irpts):mxpts).*(irpts:-1:0)/irpts;
    pin=scaletodbspl(pin,stimdb);
    output = bruce2018(pin, round(1/dt),  CF, 'nrep', nrep, 'fsmod', Fs, ...
            noiseType, implnt, 'specificSR','numsponts', trials, 'spont',spont,'tabs',tabs,'trel',trel,...
          'cohcs', cohc, 'cihcs', cihc, 'reptime', 2, species, 'outputPerSynapse');

for trial = 1:trials
        psth = squeeze(output.psth_ft(:,1, trial));        
        simtime = length(psth)/Fs;
        tvect = 0:1/Fs:simtime-1/Fs;

        ISIs = diff(tvect(logical(psth)));
        ISIs_shuf = ISIs(randperm(length(ISIs)));
        spiketimes_shuf = cumsum(ISIs_shuf);
        psth_shuf = histc(spiketimes_shuf,tvect);

        for Tlp = 1:numTs

            psthbinwidth = Ts(Tlp);
            psthbins = round(psthbinwidth*Fs);  % number of time bins per Psth bin
            numPsthbins = floor(length(psth)/psthbins);

            Psth = sum(reshape(psth(1:psthbins*numPsthbins),psthbins,numPsthbins)); %

            Psth_shuf = sum(reshape(psth_shuf(1:psthbins*numPsthbins),psthbins,numPsthbins));

            Ft(trial,Tlp) = std(Psth)^2/(mean(Psth)+eps);
            Ft_shuf(trial,Tlp) = std(Psth_shuf)^2/(mean(Psth_shuf)+eps);
            meanrate(trial,Tlp) = mean(Psth)/Ts(Tlp);

        end

end

    figure
    % Plot the calculated Fano factor curve for each trial
    loglog(Ts*1e3,Ft) 
    hold on
    % Plot the mean Fano factor curve
    loglog(Ts*1e3,mean(Ft),'k-','linewidth',2) 
    % Plot the calculated Fano factor curves for the shuffled ISIs for each trial
    loglog(Ts*1e3,Ft_shuf,'--') 
    % Plot the calculated Fano factor curves for the shuffled ISIs for each trial
    loglog(Ts*1e3,mean(Ft_shuf),'k--','linewidth',2) 
    ylabel('F(T)')
    xlabel('T (ms)')
    xlim([1e0 1e4])
    ylim([0.2 10])    
end

%% FIG 10
if flags.do_fig10 % flags.do_analyticalmeanvarcounts

    % Description:
    %%% 1. Stimuli:
    % Pure tone centred at 8 kHz (CF)
    % Duration of 0.25 s (T)
    % Presentation level: 20 dB SPL (stimdb)
    % Sampling frequency of 100 kHz (Fs)
    % Stimuli with 2.5-ms linear ramps (rt)
    % The stimuli start after 25 ms (ondelay)
    %
    %%% 2. Model configuration:
    % Normal-hearing configuration: cohc = cihc = 1
    % Cat model (species = 1)
    % Spontaneous firing rate of 100 spikes/s (spont)
    % tabs = trel = 0.6 ms
    % Variable fractional Gaussian noise (noiseType = 1)
    % Approximate implementation (implnt = 0)
    % PSTHs using bin sizes of 0.5 ms, 5 ms, and 50 ms
    % Stimuli repeated once each time the model is called (nrep = 1), but the 
    %   model is run 1000 trials (ntrials). PSTHs after the ntrials are assessed
    
    % model parameters
    CF    = 8e3;   % CF in Hz;
    cohc  = 1.0;    % normal ohc function
    cihc  = 1.0;    % normal ihc function
    species = 'cat';    % cat or human
    noiseType = 1;   % variable fGn; or fixed (frozen) fGn
    spont = 100; % spontaneous firing rate 
    tabs   = 0.6e-3; % Absolute refractory period
    trel   = 0.6e-3; % Baseline mean relative refractory period
    implnt = 0;     % "0" for approximate or "1" for actual power-law implementation

    % stimulus parameters
    F0 = CF;     % stimulus frequency in Hz
    T  = 0.25;  % stimulus duration in seconds
    rt = 2.5e-3; % rise/fall time in seconds
    stimdb = 20; % stimulus intensity in dB SPL

    % PSTH parameters
    nrep = 1;               % number of stimulus repetitions (e.g., 50);
    psthbinwidths = [5e-4 5e-3 5e-2]; % binwidth in seconds;
    numpsthbinwidths = length(psthbinwidths);
    trials = 1e3;
    % trials = 10e3; % higher number of trials gives more accurate estimates but takes longer to run

    t = 0:dt:T-dt; % time vector
    mxpts = length(t);
    irpts = rt*Fs;

    ondelay = 25e-3;

    onbin = round(ondelay*Fs);

    pin = zeros(1,onbin+mxpts);

    pin(onbin+1:onbin+mxpts) = sqrt(2)*20e-6*10^(stimdb/20)*sin(2*pi*F0*t); % unramped stimulus
    pin(onbin+1:onbin+irpts)= pin(onbin+1:onbin+irpts).*(0:(irpts-1))/irpts;
    pin(onbin+(mxpts-irpts):onbin+mxpts)=pin(onbin+(mxpts-irpts):onbin+mxpts).*(irpts:-1:0)/irpts;
    pin=scaletodbspl(pin,stimdb); 

    output = bruce2018(pin, round(1/dt), CF, 'nrep', nrep, 'fsmod', Fs, ... % signal parameters
           'varFGn', 'approxPL', species, 'outputPerSynapse', ... % general parameters
           'specificSR','numsponts', 1, 'spont',spont, 'tabs',tabs, 'trel',trel, ... % spontaneous rate parameters
           'cohcs', cohc, 'cihcs', cihc, 'reptime', 2); % hearing loss parameters

       
        
    psth = squeeze(output.psth_ft(:, 1,:));
    vihc = output.vihc;
    meanrate = output.meanrate;
    varrate = output.varrate;
    
    timeout = (0:length(psth)-1)*1/Fs;

    psthbins = zeros(numpsthbinwidths,1);
    psthtime = cell(numpsthbinwidths);
    psths = cell(numpsthbinwidths);
    mrs = cell(numpsthbinwidths);
    vrs = cell(numpsthbinwidths);

    for binlp = 1:numpsthbinwidths
    
        psthbins(binlp) = round(psthbinwidths(binlp)*Fs);  % number of psth bins per psth bin
        psthtime{binlp} = timeout(1:psthbins(binlp):end); % time vector for psth
        cnt = sum(reshape(psth,psthbins(binlp),length(psth)/psthbins(binlp))); % spike cnt in each psth bin
        mr = mean(reshape(meanrate,psthbins(binlp),length(psth)/psthbins(binlp))); % mean average of theor spike cnt in each psth bin
        vr = mean(reshape(varrate,psthbins(binlp),length(psth)/psthbins(binlp))); % mean var of theor spike cnt in each psth bin
    
        psths{binlp}(1,:) = cnt;
        mrs{binlp}(1,:) = mr;
        vrs{binlp}(1,:) = vr;
    
    end

    for lp = 2:trials
    
        amt_disp(['lp = ' int2str(lp) '/' int2str(trials)], 'volatile');
    
        [psth,meanrate,varrate,~,~,~] = bruce2018_synapse(vihc,CF,nrep,dt,noiseType,implnt,spont,tabs,trel);
    
        timeout = (0:length(psth)-1)*1/Fs;
    
        for binlp = 1:numpsthbinwidths
        
            psthbins(binlp) = round(psthbinwidths(binlp)*Fs);  % number of psth bins per psth bin
            psthtime{binlp} = timeout(1:psthbins(binlp):end); % time vector for psth
            cnt = sum(reshape(psth,psthbins(binlp),length(psth)/psthbins(binlp))); % spike cnt in each psth bin
            mr = mean(reshape(meanrate,psthbins(binlp),length(psth)/psthbins(binlp))); % mean average of theor spike cnt in each psth bin
            vr = mean(reshape(varrate,psthbins(binlp),length(psth)/psthbins(binlp))); % mean var of theor spike cnt in each psth bin
        
            psths{binlp}(lp,:) = cnt;
            mrs{binlp}(lp,:) = mr;
            vrs{binlp}(lp,:) = vr;
        
        end
    
    end
    amt_disp();
    
    for binlp = 1:numpsthbinwidths
    
        if psthbinwidths(binlp)>10e-3
            mrksize = 6;
        else
            mrksize = 2;
        end
        figure
        subplot(2,1,1)
        h1 = bar(psthtime{binlp},mean(psths{binlp}),'histc');
        set(h1,'edgecolor','k','facecolor',0.8*ones(1,3))
        ylabel('E[count]')
        xlabel('Time (s)')
        hold on
        plot(psthtime{binlp}+psthbinwidths(binlp)/2,mean(mrs{binlp})*psthbinwidths(binlp),'ro','markerfacecolor','r','markersize',mrksize,'linewidth',1)
        xlim(psthtime{binlp}([1 end]))
        title(['PSTH bin width = ' num2str(psthbinwidths(binlp)*1e3,2) 'ms'])
        subplot(2,1,2)
        h2 = bar(psthtime{binlp},var(psths{binlp}),'histc');
        set(h2,'edgecolor','k','facecolor',0.8*ones(1,3))
        xlabel('Time (s)')
        ylabel('var[count]')
        hold on
        plot(psthtime{binlp}+psthbinwidths(binlp)/2,mean(vrs{binlp})*psthbinwidths(binlp),'go','markerfacecolor','g','markersize',mrksize,'linewidth',1)
        plot(psthtime{binlp}+psthbinwidths(binlp)/2,mean(mrs{binlp})*psthbinwidths(binlp),'bo','markerfacecolor','b','markersize',mrksize,'linewidth',1)
        xlim(psthtime{binlp}([1 end]))
    
    end  
end



