function sim_fig_sub
%
% sim_fig_sub: this function will reproduce the main panel and 
% inset of Figure 9 in:
%
% Gabbiani F. and Krapp H.G. (2006). Spike-Frequency Adaptation and
% Intrinsic Properties of an Identified, Looming-Sensitive Neuron
% J. Neurophysiol. 96:2951-2962. doi:10.1152/jn.00075.2006
%
% This m-file requires conversion of lif_ad.c to a MEX file by running
% the command:
%
% MATLAB_HOME/bin/mex lif_ad.c
%
% This m-file uses functions from the Optimization Toolbox (lsqcurvefit).
%

%lif parameters
rin = 5;
taum = 8;
vth = -58;
vreset = -62;
vk = -80;
tref = 1.5;
tca = 130;
caspk = 0.2;
gahpb = 0.12;

%icurr = start_curr:curr_step:end_curr; %25;
icurr = [8 12 15];

n_iter = length(icurr);
hw = waitbar(0,'Computing...');
for i = 1:n_iter
    waitbar(i/n_iter,hw);
    [t,x] = lif_ad(icurr(i),rin,taum,vth,vreset,vk,tref,tca,caspk,gahpb);
    fr(i) = sum(x(3,:))/0.5;
    lif_adapt_dat(i).x = x;
    lif_adapt_dat(i).t = t;
    lif_adapt_dat(i).icurr = icurr(i);
end;
delete(hw);

%starts by plotting the instantaneous firing rate as a function of time
%during the current pulse obtained from direct simulation of the model
%and fit the data to a single exponential
n_curr = length(lif_adapt_dat);
icurr = [lif_adapt_dat(:).icurr];

fr_init = zeros(1,n_curr);
t_fr_init = zeros(1,n_curr);
fr_ss = zeros(1,n_curr);
fr_init_fit = zeros(1,n_curr);
fr_ss_fit = zeros(1,n_curr);
tau_fit = zeros(1,n_curr);

%typical time step in msec for the data
dt = 0.2;
t_vect = 0:dt:500;
n_t = length(t_vect);

h_f = figure(1);
h_a = axes;

hw = waitbar(0,'Computing...');
for i=1:n_curr
    waitbar(i/n_curr,hw);
    inds_spk = find(lif_adapt_dat(i).x(3,:) == 1);
    t_spk = lif_adapt_dat(i).t(inds_spk);
    if ( length(t_spk) >= 2 )
        
        n_spks = length(inds_spk);
        
        %compute the instantaneous firing rate for each trial
        fr_inst = zeros(1,n_t);
        last_fr = 0;
        t_first = t_spk(1);
        last_i = round(t_first/dt)+1;
        last_t = t_first;
        for j = 2:n_spks
            fr = 1000/(t_spk(j)-last_t);
            fr_inst(last_i) = 0.5*(last_fr + fr);
            
            ind = round(t_spk(j)/dt)+1;
            if (ind > n_t)
                warndlg('index out of bound');
                fr_inst(last_i+1:n_t) = fr;
                last_fr = fr;
                last_i = n_t;
                last_t = t_vect(n_t);
            else
                fr_inst(last_i+1:ind-1) = fr;
                last_fr = fr;
                last_i =ind;
                last_t = t_spk(j);
            end;
        end;
        fr_inst(last_i) = 0.5*last_fr;
        line('Parent',h_a,...
            'XData',t_vect,'YData',fr_inst);

        %we fit between the last index
        %corresponding to the peak firing rate and the last index
        %corresponding to steady state
        
        max_fr = max(fr_inst);
        
        %%%%%%%%%%%
        %fit between peak firing rate and steady state
        %
        inds_max = find(fr_inst == max_fr);
        %last index corresponding to peak fr
        linds_max = inds_max(end);
        linds_max_final = linds_max;
        
        t_fr_init(i) = t_vect(linds_max_final);
        
        fr_init(i) = max_fr;
        
        %assume firing rate has stabilized by 450 ms
        ind_450 = 450/dt + 1;
        fr_ss(i) = fr_inst(ind_450);
        
        inds_fit = linds_max_final:ind_450;
 
        t_fit = t_vect(inds_fit);
        t_fitz = t_fit-t_fit(1);
        fr_fit = fr_inst(inds_fit);
         
        %compute an initial estimate of the time constant
        yd1 = (fr_fit-fr_ss(i)) / (fr_init(i)-fr_ss(i));
        ind1 = find(yd1 > 0);
        yd2 = log( yd1(ind1) );

        sl_est = sum(yd2.*t_fitz(ind1))/sum(t_fitz(ind1).*t_fitz(ind1));
        tau_est = abs(1/sl_est);
        
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %version with 3 variable parameters
        %
        x0 = [fr_ss(i) fr_init(i) tau_est];
        x1 = lsqcurvefit(@s_exp,x0,t_fitz,fr_fit);
        yfit = s_exp(x1,t_fitz);
        
        fr_init_fit(i) = x1(2);
        fr_ss_fit(i) = x1(1);
        tau_fit(i) = x1(3);
        
        line('Parent',h_a,...
            'XData',t_fit,'YData',yfit,'Color',[0.5 0.5 0.5],...
            'LineWidth',2);
        
        
    else
        warn_str = sprintf('not enough spikes to compute inst. fr. for current %i',lif_adapt_dat(i).icurr);
        disp(warn_str);
    end;
end;

set(h_a,'XLim',[0 400],'YLim',[0 500]);
xlabel(h_a,'time (ms)');
ylabel(h_a,'firing rate (spk/s)');

delete(hw);

t = lif_adapt_dat(1).t;
x = lif_adapt_dat(1).x;

h_f2 = figure(2);
h_a2 = axes;

line('Parent',h_a2,'XData',t,'YData',x(1,:));

inds_spk = find(x(3,:) == 1);
for i = 1:length(inds_spk)
    tspk = t(inds_spk(i));
    v0 = x(1,inds_spk(i));
    v1 = v0 + 40;
    line('Parent',h_a2,'XData',[tspk tspk],'YData',[v0 v1]);
end;

set(h_a2,'XLim',[-20 700]);
xlabel(h_a2,'time (ms)');
ylabel(h_a2,'membrane potential (mV)');

return;

% --------------------------------------------------------------------
function [vals, jac] = s_exp(x,t_vect)
%
%this is the function that is used for a simple least square fit, without
%taking into account the SDs. The parameters are:
%
% x = [f_init f_ss tau]
%

vals = x(1) + (x(2)-x(1))*exp(-t_vect/x(3));

if ( nargout > 1 )
    t_vect = t_vect(:);
    jac(:,1) = 1-exp(-t_vect/x(3));
    jac(:,2) = exp(-t_vect/x(3));
    jac(:,3) = (x(2)-x(1))*t_vect.*x(3).^(-2).*exp(-t_vect/x(3));
end;
% --------------------------------------------------------------------

% --------------------------------------------------------------------
function vals = s_exp2(x,t_vect)
%
% this is the function that is used for a simple least square fit, without
%taking into account the SDs. The parameters are:
%
% x = tau
%

global fr_ss_lsq;
global fr_in_lsq;

vals = fr_ss_lsq + (fr_in_lsq-fr_ss_lsq)*exp(-t_vect/x(1));