Home > functions > internal > dsCalcCellProperties.m

dsCalcCellProperties

PURPOSE ^

CALCCELLPROPERTIES - calculates the intrinsic electrophysiological properties of all cells in one or more populations

SYNOPSIS ^

function stats = dsCalcCellProperties(data, varargin)

DESCRIPTION ^

CALCCELLPROPERTIES - calculates the intrinsic electrophysiological properties of all cells in one or more populations

 This is designed to be used in conjunction with the experiment
 dsProbeCellProperties which removes all connections from a model and produces
 a data array of simulated data in response to a series of hyperpolarizing and
 depolarizing pulses. This function is based on the DNSim experiment
 "cell_pulses".

 Usage:
   stats = dsCalcCellProperties(data,'option1',option1,...)

 Inputs:
   - data: array of DynaSim data structures returned by dsProbeCellProperties

 Outputs:
   - stats.(pop).(measure) [1 x num_cells] (averaged over repetitions)
   - measures (intrinsic properties):
       RMP, V_thresh, R_in, tau_m, FI_slope, CV, AR24, AR_coefficient
       FR_min (threshrate), FR_min2 (steprate?), FR_max (steprate?)
     - AP morphology: AP_amp, AP_dur (spikewidth), AP_taur, AP_taud
                      Ih_relsag, Ih_abssag, hump, AHP_amp, AHP_dur
                      AHP_time2trough, ISI_median, AR23, AR13, ISI1,
                      min_ISI_median, ISI_step_median

 Algorithm walkthrough:
   From Iinj=0:
   RMP = (avg over 50-100% step | Iinj=0)

   From largest hyperpolarizing step:
   Ih Sag = (Vend-Vmin)/|RMP-Vend|
       where Vmin=(min voltage during T sec hyperpolarizing step)
             Vend=(V at end of hyperpolarizing step)
   Ih abs sag = (Vend-Vmin)

   From last subthreshold step:
   Hump = (Vmax-Vend)/|RMP-Vend|
       where Vmax=(max voltage during depolarizing step preceding spike)
             Vend=(V at end of step)

   Across hyperpolarizing subthreshold steps:
   Rin = Input resistence (I/V slope) [4]
   taum = Membrane time constant: time for voltage relaxation to (1/e)Vmax
     where Vmax=max deflection from baseline on hyperpolarizing steps
     note: avg taum's over small drives that keep active currents silent (eg, 5-15pA)

   Across suprathreshold steps with at least two spikes:
   FI slope [Hz/nA]: slope of f/I curve (firing freq vs injected current 0-140pA) (see [2])

   Across suprathreshold steps >=60pA above first step with at least two spikes:
   AR coefficient: (slope of AR/I) where per step AR=ISI(1)/ISI(end)
   Note: AR = Adaptation ratio
   ISI_step_median = median ISI on step 60pA above first step w/ 2 spikes
   FR_step = mean FR on step 60pA above first step w/ 2 spikes
   ARif = max AR across steps >=60pA above first step w/ 2 spikes

   From first suprathreshold T sec step:
   FRmin (threshrate) = (# spikes)/T

   From first suprathreshold T sec step with at least two spikes:
   FRmin2 (steprate?) = (# spikes)/T

   From first spike of first suprathreshold step: AP morphology
   Vthresh = V( crossing(dV/dt,20mV/ms) ) %10mV/ms) )
   AP_amp = (Vpeak-Vthresh)
   AP_taur = (time to rise from 10% to 90% between Vthresh and Vpeak)
   AP_taud = (time to decay from 10% to 90% between Vpeak and Vthresh)
   AP_dur (spikewidth) = (time between rising and falling (Vthresh+APamp/2) = (Vthresh+Vpeak)/2)
   AHP_amp = (Vbaseline-Vmin) where Vmin taken during repolarizing phase
   AHP_dur (AHP duration, half-width) = time between half-peak amplitude of AHP
                                     = (time between falling and rising (Vbaseline+AHPamp/2))
   AHP_time2trough = (time between falling Vbaseline and AHPamp)
   ADPamp? ADPdur?

   From suprathreshold step 20pA above first step with at least two spikes:
   CV(ISIs over 30-100% step)

   From last suprathreshold T sec step (or step at amp=max (eg, 140pA)):
   FR_max (steprate?): (# spikes)/T
   min_ISI_median
   max_ISI
   AR24 = ISI(2)/ISI(4)

 References for methods used:
   [1] Steffensen, Scott C., et al. "Electrophysiological characterization of
     GABAergic neurons in the ventral tegmental area." The Journal of
     neuroscience 18.19 (1998): 8003-8015.
   [2] Van Aerde, Karlijn I., et al. "Flexible spike timing of layer 5 neurons
     during dynamic beta oscillation shifts in rat prefrontal cortex." The
     Journal of physiology 587.21 (2009): 5177-5196.
   [3] Connors, BW, MJ Gutnick, DA Prince. "Electrophysiological properties of
     neocortical neurons in vitro." Journal of Neurophysiology 48.6 (1982):
     1302-1320.
   [4] Povysheva, Nadezhda V., et al. "Parvalbumin-positive basket
     interneurons in monkey and rat prefrontal cortex." Journal of
     neurophysiology 100.4 (2008): 2348-2360.
   [5] Gonz?lez-Burgos, Guillermo, et al. "Functional properties of fast
     spiking interneurons and their synaptic connections with pyramidal cells in
     primate dorsolateral prefrontal cortex." Journal of Neurophysiology 93.2
     (2005): 942-953.
   [6] Gorelova, Natalia, Jeremy K. Seamans, and Charles R. Yang. "Mechanisms
     of dopamine activation of fast-spiking interneurons that exert inhibition
     in rat prefrontal cortex." Journal of neurophysiology 88.6 (2002):
     3150-3166.

 Example:
   data = dsProbeCellProperties(model)
   stats = dsCalcCellProperties(data)

 See also: dsProbeCellProperties

 Author: Jason Sherfey, PhD <jssherfey@gmail.com>
 Copyright (C) 2016 Jason Sherfey, Boston University, USA

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function stats = dsCalcCellProperties(data, varargin)
0002 %CALCCELLPROPERTIES - calculates the intrinsic electrophysiological properties of all cells in one or more populations
0003 %
0004 % This is designed to be used in conjunction with the experiment
0005 % dsProbeCellProperties which removes all connections from a model and produces
0006 % a data array of simulated data in response to a series of hyperpolarizing and
0007 % depolarizing pulses. This function is based on the DNSim experiment
0008 % "cell_pulses".
0009 %
0010 % Usage:
0011 %   stats = dsCalcCellProperties(data,'option1',option1,...)
0012 %
0013 % Inputs:
0014 %   - data: array of DynaSim data structures returned by dsProbeCellProperties
0015 %
0016 % Outputs:
0017 %   - stats.(pop).(measure) [1 x num_cells] (averaged over repetitions)
0018 %   - measures (intrinsic properties):
0019 %       RMP, V_thresh, R_in, tau_m, FI_slope, CV, AR24, AR_coefficient
0020 %       FR_min (threshrate), FR_min2 (steprate?), FR_max (steprate?)
0021 %     - AP morphology: AP_amp, AP_dur (spikewidth), AP_taur, AP_taud
0022 %                      Ih_relsag, Ih_abssag, hump, AHP_amp, AHP_dur
0023 %                      AHP_time2trough, ISI_median, AR23, AR13, ISI1,
0024 %                      min_ISI_median, ISI_step_median
0025 %
0026 % Algorithm walkthrough:
0027 %   From Iinj=0:
0028 %   RMP = (avg over 50-100% step | Iinj=0)
0029 %
0030 %   From largest hyperpolarizing step:
0031 %   Ih Sag = (Vend-Vmin)/|RMP-Vend|
0032 %       where Vmin=(min voltage during T sec hyperpolarizing step)
0033 %             Vend=(V at end of hyperpolarizing step)
0034 %   Ih abs sag = (Vend-Vmin)
0035 %
0036 %   From last subthreshold step:
0037 %   Hump = (Vmax-Vend)/|RMP-Vend|
0038 %       where Vmax=(max voltage during depolarizing step preceding spike)
0039 %             Vend=(V at end of step)
0040 %
0041 %   Across hyperpolarizing subthreshold steps:
0042 %   Rin = Input resistence (I/V slope) [4]
0043 %   taum = Membrane time constant: time for voltage relaxation to (1/e)Vmax
0044 %     where Vmax=max deflection from baseline on hyperpolarizing steps
0045 %     note: avg taum's over small drives that keep active currents silent (eg, 5-15pA)
0046 %
0047 %   Across suprathreshold steps with at least two spikes:
0048 %   FI slope [Hz/nA]: slope of f/I curve (firing freq vs injected current 0-140pA) (see [2])
0049 %
0050 %   Across suprathreshold steps >=60pA above first step with at least two spikes:
0051 %   AR coefficient: (slope of AR/I) where per step AR=ISI(1)/ISI(end)
0052 %   Note: AR = Adaptation ratio
0053 %   ISI_step_median = median ISI on step 60pA above first step w/ 2 spikes
0054 %   FR_step = mean FR on step 60pA above first step w/ 2 spikes
0055 %   ARif = max AR across steps >=60pA above first step w/ 2 spikes
0056 %
0057 %   From first suprathreshold T sec step:
0058 %   FRmin (threshrate) = (# spikes)/T
0059 %
0060 %   From first suprathreshold T sec step with at least two spikes:
0061 %   FRmin2 (steprate?) = (# spikes)/T
0062 %
0063 %   From first spike of first suprathreshold step: AP morphology
0064 %   Vthresh = V( crossing(dV/dt,20mV/ms) ) %10mV/ms) )
0065 %   AP_amp = (Vpeak-Vthresh)
0066 %   AP_taur = (time to rise from 10% to 90% between Vthresh and Vpeak)
0067 %   AP_taud = (time to decay from 10% to 90% between Vpeak and Vthresh)
0068 %   AP_dur (spikewidth) = (time between rising and falling (Vthresh+APamp/2) = (Vthresh+Vpeak)/2)
0069 %   AHP_amp = (Vbaseline-Vmin) where Vmin taken during repolarizing phase
0070 %   AHP_dur (AHP duration, half-width) = time between half-peak amplitude of AHP
0071 %                                     = (time between falling and rising (Vbaseline+AHPamp/2))
0072 %   AHP_time2trough = (time between falling Vbaseline and AHPamp)
0073 %   ADPamp? ADPdur?
0074 %
0075 %   From suprathreshold step 20pA above first step with at least two spikes:
0076 %   CV(ISIs over 30-100% step)
0077 %
0078 %   From last suprathreshold T sec step (or step at amp=max (eg, 140pA)):
0079 %   FR_max (steprate?): (# spikes)/T
0080 %   min_ISI_median
0081 %   max_ISI
0082 %   AR24 = ISI(2)/ISI(4)
0083 %
0084 % References for methods used:
0085 %   [1] Steffensen, Scott C., et al. "Electrophysiological characterization of
0086 %     GABAergic neurons in the ventral tegmental area." The Journal of
0087 %     neuroscience 18.19 (1998): 8003-8015.
0088 %   [2] Van Aerde, Karlijn I., et al. "Flexible spike timing of layer 5 neurons
0089 %     during dynamic beta oscillation shifts in rat prefrontal cortex." The
0090 %     Journal of physiology 587.21 (2009): 5177-5196.
0091 %   [3] Connors, BW, MJ Gutnick, DA Prince. "Electrophysiological properties of
0092 %     neocortical neurons in vitro." Journal of Neurophysiology 48.6 (1982):
0093 %     1302-1320.
0094 %   [4] Povysheva, Nadezhda V., et al. "Parvalbumin-positive basket
0095 %     interneurons in monkey and rat prefrontal cortex." Journal of
0096 %     neurophysiology 100.4 (2008): 2348-2360.
0097 %   [5] Gonz?lez-Burgos, Guillermo, et al. "Functional properties of fast
0098 %     spiking interneurons and their synaptic connections with pyramidal cells in
0099 %     primate dorsolateral prefrontal cortex." Journal of Neurophysiology 93.2
0100 %     (2005): 942-953.
0101 %   [6] Gorelova, Natalia, Jeremy K. Seamans, and Charles R. Yang. "Mechanisms
0102 %     of dopamine activation of fast-spiking interneurons that exert inhibition
0103 %     in rat prefrontal cortex." Journal of neurophysiology 88.6 (2002):
0104 %     3150-3166.
0105 %
0106 % Example:
0107 %   data = dsProbeCellProperties(model)
0108 %   stats = dsCalcCellProperties(data)
0109 %
0110 % See also: dsProbeCellProperties
0111 %
0112 % Author: Jason Sherfey, PhD <jssherfey@gmail.com>
0113 % Copyright (C) 2016 Jason Sherfey, Boston University, USA
0114 
0115 % Check inputs
0116 options=dsCheckOptions(varargin,{...
0117   'spike_threshold',1e-5,[],...
0118   'skip_time',10,[],... % time [ms] to exclude from detection
0119   'plot_flag',0,{0,1},...
0120   'equivalent_cells_flag',0,[],... % if true, only process one cell per pop
0121   'auto_gen_test_data_flag',0,{0,1},...
0122   },false);
0123 
0124 %% auto_gen_test_data_flag argin
0125 if options.auto_gen_test_data_flag
0126   varargs = varargin;
0127   varargs{find(strcmp(varargs, 'auto_gen_test_data_flag'))+1} = 0;
0128   varargs(end+1:end+2) = {'unit_test_flag',1};
0129   argin = [{data}, varargs]; % specific to this function
0130 end
0131 
0132 data=dsCheckData(data, varargin{:});
0133 model=data(1).model;
0134 time=data(1).time;
0135 num_times=length(time);
0136 
0137 % extract experiment parameters
0138 experiment_options=data(1).simulator_options.experiment_options;
0139 
0140 % stimulus timing
0141 onset=experiment_options.onset; %model.parameters.([pop_names{1} '_onset']);
0142 offset=experiment_options.offset; %model.parameters.([pop_names{1} '_offset']);
0143 tsel=find(time>=onset&time<=offset);
0144 
0145 % assume exactly one simulation per amplitude
0146 % if num_steps ~= length(data)
0147 %   error('there can only be one simulation per stimulus amplitude');
0148 % end
0149 
0150 % extract population info
0151 pop_names={model.specification.populations.name};
0152 num_pops=length(pop_names);
0153 
0154 % set num_cells=1 if equivalent_cells_flag
0155 if experiment_options.equivalent_cells_flag==1
0156   pop_sizes=ones(1,num_pops);
0157 else
0158   pop_sizes=[model.specification.populations.size];
0159 end
0160 
0161 % sort data by [data.(pop1)_TONIC] and sort amplitudes
0162 [amplitudes,I]=sort([data.([pop_names{1} '_TONIC'])]);
0163 data=data(I);
0164 num_steps=length(amplitudes);
0165 
0166 % get list of variables to analyze
0167 [vars,vars_pop]=dsSelectVariables(data(1).labels, varargin{:});
0168 
0169 % assume only one variable per population
0170 if length(unique(vars_pop))>num_pops
0171   [vars;vars_pop]
0172   error('there can only be one variable per population.');
0173 end
0174 
0175 % collect pulses
0176 % input=zeros(num_times,num_steps);
0177 % for s=1:num_steps
0178 %   input(:,s)=data(s).([pop_names{1} '_pulse'])(:,1);
0179 % end
0180 
0181 CF = (1e-6)/(1e-8);   % pA/um^2 => uA/cm^2. note: 1um2=1e-8cm2, 1pA=1e-6uA
0182 amplitudes_pA=amplitudes*experiment_options.membrane_area/CF;
0183 
0184 % initialize stats structure
0185 stats.experiment_options=experiment_options;
0186 stats.amplitudes=amplitudes;
0187 stats.time=time;
0188 stats.cell_results={}; % list of field names storing results for each cell
0189 stats.pop_results={};  % list of field names storing results for each population
0190 
0191 % analyze each population
0192 for p=1:num_pops
0193   % extract info for this population
0194   pop=pop_names{p};
0195   this_var=vars{strcmp(vars_pop,pop)};
0196   num_cells=pop_sizes(p);
0197   % preallocate intrinsic property measures (each will be an average over repetitions)
0198   stats.(pop).RMP     =nan(1,num_cells);
0199   stats.(pop).V_thresh=nan(1,num_cells);
0200   stats.(pop).R_in    =nan(1,num_cells);
0201   stats.(pop).tau_m   =nan(1,num_cells);
0202   stats.(pop).FI_slope=nan(1,num_cells);
0203   stats.(pop).CV      =nan(1,num_cells);
0204   stats.(pop).ISI_median=nan(1,num_cells);
0205   stats.(pop).ISI_step_median=nan(1,num_cells);
0206   stats.(pop).min_ISI_median=nan(1,num_cells);
0207   stats.(pop).max_ISI=nan(1,num_cells);
0208   stats.(pop).AR13    =nan(1,num_cells);
0209   stats.(pop).AR23    =nan(1,num_cells);
0210   stats.(pop).AR24    =nan(1,num_cells);
0211   stats.(pop).ARif    =nan(1,num_cells);
0212   stats.(pop).AR_coeff=nan(1,num_cells);
0213   stats.(pop).ISI1    =nan(1,num_cells);
0214   stats.(pop).FR_min  =nan(1,num_cells);
0215   stats.(pop).FR_min2 =nan(1,num_cells);
0216   stats.(pop).FR_step =nan(1,num_cells);
0217   stats.(pop).FR_max  =nan(1,num_cells);
0218   stats.(pop).AP_amp  =nan(1,num_cells);
0219   stats.(pop).AP_dur  =nan(1,num_cells);
0220   stats.(pop).AP_taur =nan(1,num_cells);
0221   stats.(pop).AP_taud =nan(1,num_cells);
0222   stats.(pop).Ih_relsag  =nan(1,num_cells);
0223   stats.(pop).Ih_abssag=nan(1,num_cells);
0224   stats.(pop).hump    =nan(1,num_cells);
0225   stats.(pop).AHP_amp =nan(1,num_cells);
0226   stats.(pop).AHP_dur =nan(1,num_cells);
0227   stats.(pop).AHP_time2trough=nan(1,num_cells);
0228   % determine whether cells are spiking or not on each step
0229   spike_times=cell(num_steps,num_cells);
0230   for c=1:num_cells
0231     for s=1:num_steps
0232       % select trace for this (pop,cell,step)
0233       X=data(s).(this_var)(tsel,c);
0234       % get spikes in this cell during step
0235       spike_inds=1+find((X(2:end)>=options.spike_threshold & X(1:end-1)<options.spike_threshold));
0236       spike_times{s,c}=time(tsel(spike_inds));
0237     end
0238     num_spikes=cellfun(@numel,spike_times(:,c));
0239     is_spiking=(num_spikes>0); % {0:subthreshold,1:suprathreshold}
0240 
0241     % Calculate measures of cell intrinsic properties
0242     % 1) calculate RMP (avg over repetitions) From steps with amp=0
0243     % RMP = (avg over 50-100% step | Iinj=0)
0244     step_sel=find(amplitudes==0); % select all simulations with amp=0
0245     time_sel=tsel(round(.5*numel(tsel)):end); % select 50-100% of step
0246     rmp=0;
0247     for s=1:length(step_sel)
0248       rmp=rmp+nanmean(data(step_sel(s)).(this_var)(time_sel,c));
0249     end
0250     stats.(pop).RMP(c)=rmp/length(step_sel);
0251 
0252     % 2) calculate Ih_relsag (avg over repetitions) From largest hyperpolarizing step
0253     % Ih Sag = (Vend-Vmin)/|RMP-Vend|
0254     %     where Vmin=(min voltage during T sec hyperpolarizing step)
0255     %           Vend=(V at end of hyperpolarizing step)
0256     step_sel=find(amplitudes==min(amplitudes) & amplitudes<0);
0257     sag=0; abssag=0;
0258     for s=1:length(step_sel)
0259       V=data(step_sel(s)).(this_var)(:,c);
0260       bl=V(tsel(1)-1);   % baseline value is point immediately before stim onset
0261       Vend=V(tsel(end)); % final point
0262       Vmin=min(V(tsel)); % minimum point of sag
0263       sag=sag+((Vend-Vmin)/abs(bl-Vend));
0264       abssag=abssag+(Vend-Vmin);
0265       %figure; plot(time,V); line(xlim,[Vmin Vmin]); line(xlim,[Vend Vend]); line(xlim,[bl bl]);
0266     end
0267     stats.(pop).Ih_relsag(c)=sag/length(step_sel);
0268     stats.(pop).Ih_abssag(c)=abssag/length(step_sel);
0269 
0270     % 3) calculate hump (avg over repetitions) From last subthreshold step
0271     % Hump = (Vmax-Vend)/|RMP-Vend|
0272     %     where Vmax=(max voltage during depolarizing step preceding spike)
0273     %           Vend=(V at end of step)
0274     step_sel=max(1,find(num_spikes>0,1,'first')-1);
0275     if ~isempty(step_sel)
0276       V=data(step_sel).(this_var)(:,c);
0277       bl=V(tsel(1)-1);   % baseline value is point immediately before stim onset
0278       Vend=V(tsel(end)); % final point
0279       Vmax=max(V(tsel)); % maximum point of hump
0280       stats.(pop).hump(c)=((Vmax-Vend)/abs(bl-Vend));
0281     end
0282 
0283     % 4) calculate (R_in,tau_m) (from avg over repetitions) Across hyperpolarizing subthreshold steps
0284     % Rin = Input resistence (I/V slope) [4]
0285     % taum = Membrane time constant: time for voltage relaxation to (1/e)Vmax
0286     %   where Vmax=max deflection from baseline on hyperpolarizing steps
0287     %   note: avg taum's over small drives that keep active currents silent (eg, 5-15pA)
0288     step_sel=find(num_spikes==0 & amplitudes'<0);
0289     amps=amplitudes(step_sel);
0290     uamps=unique(amps);
0291     nuamps=length(uamps);
0292     Veq=nan(1,nuamps);
0293     taum=nan(1,nuamps);
0294     time_sel=tsel(round(.5*numel(tsel)):end); % select 50-100% of step
0295     % loop over unique amplitudes
0296     for a=1:nuamps
0297       asel=find(amps==uamps(a)); % indices to subthreshold amps with this value
0298       % loop over repetitions of the same amplitude
0299       veq=0; tau=0;
0300       for l=1:length(asel)
0301         step=step_sel(asel(l)); % index to this simulation
0302         X=data(step).(this_var)(:,c);
0303         % store mean voltage over 50-100% step
0304         veq=veq+nanmean(X(time_sel));
0305         % calc membrane time constant based on this step (time to Vmax(1/e))
0306         bl=X(tsel(1)-1); % baseline value is point immediately before stim onset
0307         V=X-bl; % shift baseline to V=0
0308         if uamps(a)<0
0309           V=abs(V); % invert values so that deflection is positive
0310         end
0311         Vmax=V(tsel(end)); % max is final point during stim period before offset
0312         Vthresh=Vmax*(1/exp(1)); % voltage at 1/e
0313         Vdecay=V(tsel(end):end); % voltage decay after stim offset
0314         tthresh=time(tsel(end)+find(Vdecay<Vthresh,1,'first')-1); % time at which decay crosses 1/e
0315         tau=tau+(tthresh-offset); % time to drop to 1/e after stim offset
0316       end
0317       Veq(a)=veq/length(asel);
0318       if any(tau)
0319         taum(a)=tau/length(asel);
0320       end
0321     end
0322     % calc R_in (from slope of amp/Veq)
0323     if any(~isnan(Veq))
0324       sel=~isnan(Veq);
0325       P=polyfit(uamps(sel),Veq(sel),1);
0326       stats.(pop).R_in(c)=P(1);
0327     end
0328     if any(~isnan(taum))
0329       stats.(pop).tau_m(c)=taum(find(~isnan(taum),1,'first'));%1);%nanmedian(taum);
0330     end
0331 
0332     % 5) calculate FI_slope (from avg over repetitions) Across suprathreshold steps with at least two spikes
0333     % FI slope: slope of f/I curve (firing freq vs injected current 0-140pA) (see [2])
0334 %     step_sel=find(num_spikes>1 & amplitudes'>0);
0335 %     amps=amplitudes(step_sel);
0336 %     uamps=unique(amps);
0337 %     nuamps=length(uamps);
0338 %     FR=nan(1,nuamps);
0339 %     % loop over unique amplitudes
0340 %     for a=1:nuamps
0341 %       asel=find(amps==uamps(a)); % indices to subthreshold amps with this value
0342 %       % loop over repetitions of the same amplitude
0343 %       fr=0;
0344 %       for l=1:length(asel)
0345 %         step=step_sel(asel(l)); % index to this simulation
0346 %         fr=fr+(num_spikes(step)/((offset-onset)/1000));
0347 %       end
0348 %       FR(a)=fr/length(asel); % [Hz]
0349 %     end
0350 %     % calc FI_slope
0351 %     if any(~isnan(FR))
0352 %       sel=~isnan(FR);
0353 %       amps_nA=uamps(sel)*experiment_options.membrane_area/CF/1000;
0354 %       P=polyfit(amps_nA,FR(sel),1);
0355 %       stats.(pop).FI_slope(c)=P(1); % [Hz/nA]
0356 %       figure; plot(amps_nA,FR(sel)); xlabel('amps [nA]'); ylabel('FR [Hz]');
0357 %       [num_spikes(step_sel) amplitudes(step_sel)']
0358 %     end
0359 
0360     % 6) calculate ARs (avg over repetitions) & AR_coefficient Across
0361     %    suprathreshold steps >=60pA above first step with at least two spikes
0362     % AR coefficient: (slope of AR/I) where per step AR=ISI(1)/ISI(end)
0363     thresh_step=find(num_spikes>1,1,'first');
0364     if any(thresh_step)
0365       step_sel=find(amplitudes_pA>(amplitudes_pA(thresh_step)+60));
0366     else
0367       step_sel=[];
0368     end
0369     if any(step_sel)
0370       amps=amplitudes(step_sel);
0371       uamps=unique(amps);
0372       nuamps=length(uamps);
0373       AR=nan(1,nuamps);
0374       FR=nan(1,nuamps);
0375       % loop over unique amplitudes
0376       for a=1:nuamps
0377         asel=find(amps==uamps(a)); % indices to subthreshold amps with this value
0378         % loop over repetitions of the same amplitude
0379         ar=0; denom=0;
0380         fr=0;
0381         for l=1:length(asel)
0382           step=step_sel(asel(l)); % index to this simulation
0383           fr=fr+(num_spikes(step)/((offset-onset)/1000));
0384           ISI=diff(spike_times{step,c});
0385           if length(ISI)>1
0386             denom=denom+1;
0387   %           if length(ISI)>2
0388   %             ar=ar+(ISI(2)/ISI(end));
0389   %           else
0390               ar=ar+(ISI(1)/ISI(end));
0391   %           end
0392           end
0393         end
0394         AR(a)=ar/denom;
0395         FR(a)=fr/length(asel); % [Hz]
0396       end
0397       % calc ISI_median at 60pA above threshold
0398       spikes=spike_times{step_sel(1),c};
0399       ISI=diff(spikes);
0400       stats.(pop).ISI_step_median(c)=median(ISI);
0401       % store FR at 60pA above threshold
0402       stats.(pop).FR_step(c)=FR(1); % FR at 60pA above threshold
0403       if ~strcmp(reportUI,'matlab') && exist('nanmax') ~= 2 % 'nanmax is not in Octave's path
0404         try
0405           pkg load statistics; % trying to load octave forge 'statistics' package before using nanmax function
0406         catch
0407           error('nanmax function is needed, please install the statistics package from Octave Forge');
0408         end
0409       end
0410       stats.(pop).ARif(c)=nanmax(AR); % nanmean, nanmedian
0411       % calculate AR_coefficient
0412       if any(~isnan(AR))
0413         sel=~isnan(AR);
0414         P=polyfit(uamps(sel),AR(sel),1);
0415         stats.(pop).AR_coeff(c)=P(1);
0416         %figure; plot(uamps(sel),AR(sel)); xlabel('amps'); ylabel('AR');
0417       end
0418       % calc FI_slope
0419       if any(~isnan(FR))
0420         sel=~isnan(FR);
0421         amps_nA=uamps(sel)*experiment_options.membrane_area/CF/1000;
0422         P=polyfit(amps_nA,FR(sel),1);
0423         stats.(pop).FI_slope(c)=P(1); % [Hz/nA]
0424         %figure; plot(amps_nA,FR(sel)); xlabel('amps [nA]'); ylabel('FR [Hz]');
0425         %[num_spikes(step_sel) amplitudes(step_sel)']
0426       end
0427     end
0428 
0429     % 7) calculate FR_min From first suprathreshold T sec step
0430     % FRmin (threshrate) = (# spikes)/T
0431     step_sel=find(num_spikes>0,1,'first');
0432     if any(step_sel)
0433       stats.(pop).FR_min(c)=num_spikes(step_sel)/((offset-onset)/1000);
0434     end
0435 
0436     % 8) calculate FR_min2 From first suprathreshold T sec step with at least two spikes
0437     % FRmin2 (steprate?) = (# spikes)/T
0438     step_sel=find(num_spikes>1,1,'first');
0439     if any(step_sel)
0440       stats.(pop).FR_min2(c)=num_spikes(step_sel)/((offset-onset)/1000);
0441       stats.(pop).ISI1(c)=(spike_times{step_sel,c}(2)-spike_times{step_sel,c}(1));
0442     end
0443 
0444     % 9) calculate CV (avg over repetitions) From suprathreshold step 20pA above first step with at least two spikes
0445     % CV(ISIs over 30-100% step)
0446     tmin=time(tsel(round(.3*numel(tsel)))); % time at 30% through step
0447     thresh_step=find(num_spikes>1,1,'first');
0448     if any(thresh_step)
0449       step_sel=find(amplitudes_pA>(amplitudes_pA(thresh_step)+20));
0450     else
0451       step_sel=[];
0452     end
0453     if any(step_sel)
0454       spikes=spike_times{step_sel,c};
0455       spikes=spikes(spikes>tmin);
0456       ISI=diff(spikes);
0457       if any(ISI)
0458         stats.(pop).CV(c)=std(ISI)/mean(ISI);
0459       end
0460       spikes=spike_times{step_sel,c};
0461       ISI=diff(spikes);
0462       stats.(pop).ISI_median(c)=median(ISI);
0463       stats.(pop).max_ISI(c)=max(ISI);
0464     end
0465 
0466     % 10) calculate (FRmax,AR24) From last suprathreshold T sec step
0467     % FRmax (steprate?): (# spikes)/T
0468     % AR24 = ISI(2)/ISI(4)
0469     step_sel=find(num_spikes>4,1,'last');
0470     if any(step_sel)
0471       spikes=spike_times{step_sel,c};
0472       ISIs=diff(spikes)/1000;
0473       finst=1./(ISIs);
0474       stats.(pop).AR24(c)=finst(2)/finst(4);
0475 %       stats.(pop).AR23(c)=ISIs(2)/ISIs(3);
0476 %       stats.(pop).AR13(c)=ISIs(1)/ISIs(3);
0477       stats.(pop).FR_max(c)=num_spikes(step_sel)/((offset-onset)/1000);
0478       stats.(pop).min_ISI_median(c)=median(diff(spikes));
0479     end
0480     step_sel=find(num_spikes>3,1,'first');
0481     if any(step_sel)
0482       spikes=spike_times{step_sel,c};
0483       ISIs=diff(spikes)/1000;
0484       stats.(pop).AR23(c)=ISIs(2)/ISIs(3);
0485       stats.(pop).AR13(c)=ISIs(1)/ISIs(3);
0486     end
0487 
0488     % 11) calculate AP morphology From first spike of first suprathreshold step with at least two spikes
0489     step_sel=find(num_spikes>0,1,'first');
0490     if any(step_sel)
0491       X=double(data(step_sel).(this_var)(:,c));
0492       spks=spike_times{step_sel,c};
0493       spk_1=spks(1); % time of first spike
0494       if length(spks)>1
0495         spk_2=spks(2); % time of second spike
0496       else
0497         spk_2=inf;
0498       end
0499       pad=100; % ms, time before and after spike detection (make longer than expected AHP)
0500       spk_beg=max(spk_1-pad,onset);
0501       spk_end=min(spk_1+pad,spk_2); % make sure spike interval excludes the following spike
0502       spk_beg_i=nearest(time,spk_beg);
0503       spk_end_i=nearest(time,spk_end);
0504       spk_inds=spk_beg_i:spk_end_i; % indices for this spike
0505       t=time(spk_inds); % times around spike
0506       V=X(spk_inds);  % trace around spike
0507       % Vthresh = V( crossing(dV/dt,10mV/ms) )
0508       dVdt=diff(V)/(t(2)-t(1));
0509       dVdt=smooth(dVdt,round(1/(t(2)-t(1)))); % 1ms smoothing
0510       thresh_ind=find(dVdt>20,1,'first');%crossing(dVdt,t,10);
0511       Vthresh=V(thresh_ind(1));
0512       % APamp = (Vpeak-Vthresh)
0513       [pk,loc]=findpeaks(V,'NPeaks',1);
0514       Vpeak=V(loc);%max(V);
0515       Vpeak_i=loc;%find(V==Vpeak,1,'first');
0516       APamp=Vpeak-Vthresh;
0517       V10=Vthresh+.1*APamp; % 10% from Vthresh to Vpeak
0518       V90=Vthresh+.9*APamp; % 90% from Vthresh to Vpeak
0519       % depolarizing rising phase
0520       V10_i_r=1+find(V(2:end)>=V10 & V(1:end-1)<V10); % first
0521       V90_i_r=1+find(V(2:end)>=V90 & V(1:end-1)<V90); % second
0522       % APtaur = (time to rise from 10% to 90% between Vthresh and Vpeak)
0523       if any(V10_i_r) && any(V90_i_r)
0524         APtaur=t(V90_i_r(1))-t(V10_i_r(1));
0525       else
0526         APtaur=nan;
0527       end
0528       % repolarizing falling phase
0529       V10_i_d=1+find(V(1:end-1)>=V10 & V(2:end)<V10); % second
0530       V90_i_d=1+find(V(1:end-1)>=V90 & V(2:end)<V90); % first
0531       if numel(V10_i_d)>1 && numel(V10_i_d)>1
0532         V10_i_d=V10_i_d(end);
0533         V90_i_d=V90_i_d(end);
0534       end
0535       if isempty(V10_i_d)
0536         % set to the minimum point of the repolarizing phase
0537         V10=min(V(Vpeak_i:end));
0538         V10_i_d=find(V(Vpeak_i:end)==V10)+Vpeak_i-1;
0539       end
0540       % APtaud = (time to decay from 10% to 90% between Vpeak and Vthresh)
0541       if any(V10_i_d) && any(V90_i_d)
0542         APtaud=t(V10_i_d(1))-t(V90_i_d(1));
0543       else
0544         APtaud=nan;
0545       end
0546       % APdur (spikewidth) = (time between rising and falling (Vthresh+APamp/2) = (Vthresh+Vpeak)/2)
0547       V50=Vthresh+.5*APamp;
0548       V50_i_r=1+find(V(2:end)>=V50 & V(1:end-1)<V50);
0549       V50_i_d=1+find(V(1:end-1)>=V50 & V(2:end)<V50);
0550       if any(V50_i_d) && any(V50_i_r)
0551         APdur=t(V50_i_d(1))-t(V50_i_r(1));
0552       else
0553         APdur=nan;
0554       end
0555       % AHPamp = (Vbaseline-Vmin) where Vmin taken during repolarizing phase
0556       %bl=X(spk_inds(1)-1); % baseline voltage
0557       bl=mean(V);
0558       % find trough: look for first peak in the inverted post-spike trace
0559       [pk,loc]=findpeaks(-smooth(V(V10_i_d:end),100),'NPeaks',1);
0560       ahp_trough_i=V10_i_d+loc-1;
0561       Vmin=V(ahp_trough_i);
0562       %Vmin=-findpeaks(-V(V10_i_d:end),'NPeaks',1);
0563       %Vmin=max(findpeaks(-V(V10_i_d:end)));
0564       %Vmin=min(V(V10_i_d:end));
0565       AHPamp=abs(bl-Vmin);
0566       % AHPdur (AHP duration, half-width) = time between half-peak amplitude of AHP
0567       %                                   = (time between falling and rising (Vbaseline+AHPamp/2))
0568       ahp_V50=bl+.5*AHPamp;
0569       ahp_V50_i_d=1+find(V(1:end-1)>=ahp_V50 & V(2:end)<ahp_V50); % first
0570       ahp_V50_i_d(ahp_V50_i_d<V10_i_d)=[]; % remove crossings before repolarization
0571       ahp_V50_i_r=1+find(V(2:end)>=ahp_V50 & V(1:end-1)<ahp_V50); % second
0572       if any(ahp_V50_i_d)
0573         ahp_V50_i_r(ahp_V50_i_r<ahp_V50_i_d(1))=[]; % remove crossings before start of AHP
0574       end
0575       if any(ahp_V50_i_r) && any(ahp_V50_i_d)
0576         AHPdur=t(ahp_V50_i_r(1))-t(ahp_V50_i_d(1));
0577       else
0578         AHPdur=nan;
0579       end
0580       % AHP_time2trough = (time between falling Vbaseline and Vmin)
0581 %       ahp_bl_i_d=1+find(V(1:end-1)>=ahp_V50 & V(2:end)<ahp_V50); % first
0582 %       ahp_bl_i_d(ahp_bl_i_d<V10_i_d)=[]; % remove crossings before repolarization
0583       %ahp_trough_i=find(V==Vmin);
0584       %ahp_trough_i(ahp_trough_i<V10_i_d)=[]; % remove crossings before start
0585       if any(V10_i_d)
0586         AHPtime2trough=t(ahp_trough_i(1))-t(Vpeak_i);%t(V10_i_d(1));
0587         if options.plot_flag
0588           figure; plot(t,V);
0589           line(xlim,[V10 V10]); line(xlim,[Vmin Vmin]);
0590           line([t(ahp_trough_i(1)) t(ahp_trough_i(1))],ylim);
0591           line([t(Vpeak_i) t(Vpeak_i)],ylim,'color','r');
0592         end
0593       else
0594         AHPtime2trough=nan;
0595       end
0596       if options.plot_flag
0597         figure; plot(t,V);
0598         line(xlim,[bl bl]);
0599         line(xlim,[Vthresh Vthresh]);
0600         line(xlim,[Vpeak Vpeak]);
0601         line(xlim,[V10 V10]);
0602         line([t(V10_i_r(1)) t(V10_i_r(1))],ylim);
0603         line([t(V10_i_d(1)) t(V10_i_d(1))],ylim);
0604         line(xlim,[V50 V50]);
0605         line(xlim,[V90 V90]);
0606         line(xlim,[ahp_V50 ahp_V50],'color','r');
0607         line([t(ahp_V50_i_r(1)) t(ahp_V50_i_r(1))],ylim,'color','r');
0608         line([t(ahp_V50_i_d(1)) t(ahp_V50_i_d(1))],ylim,'color','r');
0609       end
0610       stats.(pop).V_thresh(c)=Vthresh;
0611       stats.(pop).AP_amp(c)=APamp;
0612       stats.(pop).AP_taur(c)=APtaur;
0613       stats.(pop).AP_taud(c)=APtaud;
0614       stats.(pop).AP_dur(c)=APdur;
0615       stats.(pop).AHP_amp(c)=AHPamp;
0616       stats.(pop).AHP_dur(c)=AHPdur;
0617       stats.(pop).AHP_time2trough(c)=AHPtime2trough;
0618     end
0619   end
0620   % collect data for this population across simulations
0621   % note: each simulation has a different input amplitude
0622   X=zeros(num_steps,num_times,num_cells);
0623   for s=1:num_steps
0624     X(s,:,:)=data(s).(this_var);
0625   end
0626   % calculate simple means
0627   if ~strcmp(reportUI,'matlab') && exist('nanmean') ~= 2 % 'nanmean is not in Octave's path
0628     try
0629       pkg load statistics; % trying to load octave forge 'statistics' package before using nanmean function
0630     catch
0631       error('nanmean function is needed, please install the statistics package from Octave Forge');
0632     end
0633   end
0634   means=nanmean(X(:,tsel,:),2); % average over select times
0635   % store means in stats structure
0636   stats.([this_var '_mean_per_amp'])=squeeze(means);
0637   stats.([this_var '_pop_mean_per_amp'])=nanmean(means,3);
0638   stats.([this_var '_pop_mean_per_time'])=nanmean(X,3);
0639 end
0640 
0641 if options.plot_flag
0642   v=1;
0643   figure('position',[180 330 1450 530])
0644   subplot(2,2,1); % V(t)
0645   plot(time,stats.([vars{v} '_pop_mean_per_time']));
0646   xlabel('time [ms]'); ylabel(['<' strrep(vars{v},'_','\_') ', pop>']);
0647   legend(cellfun(@(x)['I=' num2str(x)],num2cell(amplitudes),'uni',0));
0648   subplot(2,2,3); % I(t)
0649   %plot(time,input); xlabel('time [ms]'); ylabel('I(t)');
0650   %legend(cellfun(@(x)['I=' num2str(x)],num2cell(amplitudes),'uni',0));
0651   subplot(2,2,2); % I/V
0652   plot(amplitudes,stats.([vars{v} '_mean_per_amp'])); hold on
0653   plot(amplitudes,stats.([vars{v} '_pop_mean_per_amp']),'k-','linewidth',5);
0654   xlabel('amplitude'); ylabel(['<' strrep(vars{v},'_','\_') ', time>']);
0655 end
0656 
0657 %% auto_gen_test_data_flag argout
0658 if options.auto_gen_test_data_flag
0659   argout = {stats}; % specific to this function
0660 
0661   dsUnitSaveAutoGenTestData(argin, argout);
0662 end
0663 
0664 end
0665 
0666 
0667 % check how Tallie calculated:
0668 % - threshrate (mean spike rate on tonic depol just above threshold)
0669 % - steprate (mean spike rate on final? step depol)
0670 % - AHP 5-20ms (Q: mean post-spike AHP amplitude over 5-20ms after trough?)
0671 % - SpikeAmp (same as [4])
0672 % - SpikeWidth (Spike width at half height) (same as [4])
0673 % - RMP
0674 
0675 % AHPtau (AHP duration, half-width) = time between half-peak amplitude of AHP
0676 
0677 % From Iinj=0:
0678 % RMP: resting membrane potential [mV] = avg V over step 150-500ms
0679 
0680 % From first spike:
0681 % Vthresh (spike threshold) [4]: level of voltage deflection exceeding 20mV/1ms %10mV/1ms
0682 % Peak amplitude [4]: (peak - threshold value)
0683 % Spike rise time [4]: time to rise from 10% to 90% of peak amplitude
0684 % Spike decay time [4]: time to decay from 10% to 90% of the amplitude b/w peak and spike threshold
0685 % Spike duration (half-width) [1,4]: "time between half-peak amplitude for the falling and rising edges"
0686 
0687 % Other measures from [4]:
0688 % Sag (Ih?) = (Vmin-Vend)/|RMP-Vend|
0689 %     where Vmin=(min voltage during 500ms hyperpolarizing step)
0690 %           Vend=(V at end of hyperpolarizing step)
0691 % Hump = (Vmax-Vend)/|RMP-Vend|
0692 %     where Vmax=(max voltage during depolarizing step preceding spike)
0693 %           Vend=(V at end of step)
0694 % Adaptation ratio AR = ISI1/ISIend = f(step amplitude)
0695 % AR coefficient = slope of (step amp, AR) for amp > 60pA above spike threshold
0696 % Coefficient of variation CV of ISIs was measured from spikes during
0697 %   150-500ms at depolarizing pulse 20pA above spike threshold
0698 
0699 % Measures from [2]:
0700 % FR: calculate from total spikes elicited by 1sec current injection at 140pA (see [2])
0701 % AR24: Adaptation ratio: ratio of inst. freq of 2nd and 4th spike intervals in train (see [2])

Generated on Tue 12-Dec-2017 11:32:10 by m2html © 2005