rmeddis@0
|
1
|
rmeddis@0
|
2 function MAP1_14(inputSignal, sampleRate, BFlist, MAPparamsName, ...
|
rmeddis@0
|
3 AN_spikesOrProbability, paramChanges)
|
rmeddis@0
|
4 % To test this function use test_MAP1_14 in this folder
|
rmeddis@0
|
5 %
|
rmeddis@0
|
6 % All arguments are mandatory.
|
rmeddis@0
|
7 %
|
rmeddis@0
|
8 % BFlist is a list of BFs but can be '-1' to allow MAPparams to choose
|
rmeddis@0
|
9 %
|
rmeddis@0
|
10
|
rmeddis@0
|
11 % MAPparamsName='Normal'; % source of model parameters
|
rmeddis@0
|
12 % AN_spikesOrProbability='spikes'; % or 'probability'
|
rmeddis@0
|
13 % paramChanges is a cell array of strings that can be used to make last
|
rmeddis@0
|
14 % minute parameter changes, e.g., to simulate OHC loss
|
rmeddis@0
|
15 % paramChanges{1}= 'DRNLParams.a=0;';
|
rmeddis@0
|
16
|
rmeddis@0
|
17 % The model parameters are established in the MAPparams<***> file
|
rmeddis@0
|
18 % and stored as global
|
rmeddis@0
|
19
|
rmeddis@0
|
20 restorePath=path;
|
rmeddis@0
|
21 addpath (['..' filesep 'parameterStore'])
|
rmeddis@0
|
22
|
rmeddis@0
|
23 global OMEParams DRNLParams IHC_cilia_RPParams IHCpreSynapseParams
|
rmeddis@0
|
24 global AN_IHCsynapseParams MacGregorParams MacGregorMultiParams
|
rmeddis@0
|
25
|
rmeddis@0
|
26 % All of the results of this function are stored as global
|
rmeddis@0
|
27 global dt ANdt savedBFlist saveAN_spikesOrProbability saveMAPparamsName...
|
rmeddis@0
|
28 savedInputSignal OMEextEarPressure TMoutput OMEoutput ARattenuation ...
|
rmeddis@0
|
29 DRNLoutput IHC_cilia_output IHCrestingCiliaCond IHCrestingV...
|
rmeddis@0
|
30 IHCoutput ANprobRateOutput ANoutput savePavailable tauCas ...
|
rmeddis@0
|
31 CNoutput ICoutput ICmembraneOutput ICfiberTypeRates MOCattenuation
|
rmeddis@0
|
32
|
rmeddis@0
|
33 % Normally only ICoutput(logical spike matrix) or ANprobRateOutput will be
|
rmeddis@0
|
34 % needed by the user; so the following will suffice
|
rmeddis@0
|
35 % global ANdt ICoutput ANprobRateOutput
|
rmeddis@0
|
36
|
rmeddis@0
|
37 % Note that sampleRate has not changed from the original function call and
|
rmeddis@0
|
38 % ANprobRateOutput is sampled at this rate
|
rmeddis@0
|
39 % However ANoutput, CNoutput and IC output are stored as logical
|
rmeddis@0
|
40 % 'spike' matrices using a lower sample rate (see ANdt).
|
rmeddis@0
|
41
|
rmeddis@0
|
42 % When AN_spikesOrProbability is set to probability,
|
rmeddis@0
|
43 % no spike matrices are computed.
|
rmeddis@0
|
44 % When AN_spikesOrProbability is set to 'spikes',
|
rmeddis@0
|
45 % no probability output is computed
|
rmeddis@0
|
46
|
rmeddis@0
|
47 % Efferent control variables are ARattenuation and MOCattenuation
|
rmeddis@0
|
48 % These are scalars between 1 (no attenuation) and 0.
|
rmeddis@0
|
49 % They are represented with dt=1/sampleRate (not ANdt)
|
rmeddis@0
|
50 % They are computed using either AN probability rate output
|
rmeddis@0
|
51 % or IC (spikes) output as approrpriate.
|
rmeddis@0
|
52 % AR is computed using across channel activity
|
rmeddis@0
|
53 % MOC is computed on a within-channel basis.
|
rmeddis@0
|
54
|
rmeddis@0
|
55
|
rmeddis@0
|
56 % save as global for later plotting if required
|
rmeddis@0
|
57 savedBFlist=BFlist;
|
rmeddis@0
|
58 saveAN_spikesOrProbability=AN_spikesOrProbability;
|
rmeddis@0
|
59 saveMAPparamsName=MAPparamsName;
|
rmeddis@0
|
60
|
rmeddis@0
|
61 % Read parameters from MAPparams<***> file in 'parameterStore' folder
|
rmeddis@0
|
62 cmd=['method=MAPparams' MAPparamsName ...
|
rmeddis@0
|
63 '(BFlist, sampleRate, 0);'];
|
rmeddis@0
|
64 eval(cmd);
|
rmeddis@0
|
65
|
rmeddis@0
|
66 % Beware, 'BFlist=-1' is a legitimate argument for MAPparams<>
|
rmeddis@0
|
67 % if the calling program allows MAPparams to specify the list
|
rmeddis@0
|
68 BFlist=DRNLParams.nonlinCFs;
|
rmeddis@0
|
69
|
rmeddis@0
|
70 % now accept last mintue parameter changes required by the calling program
|
rmeddis@0
|
71 if nargin>5 && ~isempty(paramChanges)
|
rmeddis@0
|
72 nChanges=length(paramChanges);
|
rmeddis@0
|
73 for idx=1:nChanges
|
rmeddis@0
|
74 eval(paramChanges{idx})
|
rmeddis@0
|
75 end
|
rmeddis@0
|
76 end
|
rmeddis@0
|
77
|
rmeddis@0
|
78 dt=1/sampleRate;
|
rmeddis@0
|
79 duration=length(inputSignal)/sampleRate;
|
rmeddis@0
|
80 % segmentDuration is specified in parameter file (must be >efferent delay)
|
rmeddis@0
|
81 segmentDuration=method.segmentDuration;
|
rmeddis@0
|
82 segmentLength=round(segmentDuration/ dt);
|
rmeddis@0
|
83 segmentTime=dt*(1:segmentLength); % used in debugging plots
|
rmeddis@0
|
84
|
rmeddis@0
|
85 % all spiking activity is computed using longer epochs
|
rmeddis@0
|
86 ANspeedUpFactor=5; % 5 times longer
|
rmeddis@0
|
87
|
rmeddis@0
|
88 % inputSignal must be row vector
|
rmeddis@0
|
89 [r c]=size(inputSignal);
|
rmeddis@0
|
90 if r>c, inputSignal=inputSignal'; end % transpose
|
rmeddis@0
|
91 % ignore stereo signals
|
rmeddis@0
|
92 inputSignal=inputSignal(1,:); % drop any second channel
|
rmeddis@0
|
93 savedInputSignal=inputSignal;
|
rmeddis@0
|
94
|
rmeddis@0
|
95 % Segment the signal
|
rmeddis@0
|
96 % The sgment length is given but the signal length must be adjusted to be a
|
rmeddis@0
|
97 % multiple of both the segment length and the reduced segmentlength
|
rmeddis@0
|
98 [nSignalRows signalLength]=size(inputSignal);
|
rmeddis@0
|
99 segmentLength=ceil(segmentLength/ANspeedUpFactor)*ANspeedUpFactor;
|
rmeddis@0
|
100 % Make the signal length a whole multiple of the segment length
|
rmeddis@0
|
101 nSignalSegments=ceil(signalLength/segmentLength);
|
rmeddis@0
|
102 padSize=nSignalSegments*segmentLength-signalLength;
|
rmeddis@0
|
103 pad=zeros(nSignalRows,padSize);
|
rmeddis@0
|
104 inputSignal=[inputSignal pad];
|
rmeddis@0
|
105 [ignore signalLength]=size(inputSignal);
|
rmeddis@0
|
106
|
rmeddis@0
|
107 % AN (spikes) is computed at a lower sample rate when spikes required
|
rmeddis@0
|
108 % so it has a reduced segment length (see 'ANspeeUpFactor' above)
|
rmeddis@0
|
109 % AN CN and IC all use this sample interval
|
rmeddis@0
|
110 ANdt=dt*ANspeedUpFactor;
|
rmeddis@0
|
111 reducedSegmentLength=round(segmentLength/ANspeedUpFactor);
|
rmeddis@0
|
112 reducedSignalLength= round(signalLength/ANspeedUpFactor);
|
rmeddis@0
|
113
|
rmeddis@0
|
114 %% Initialise with respect to each stage before computing
|
rmeddis@0
|
115 % by allocating memory,
|
rmeddis@0
|
116 % by computing constants
|
rmeddis@0
|
117 % by establishing easy to read variable names
|
rmeddis@0
|
118 % The computations are made in segments and boundary conditions must
|
rmeddis@0
|
119 % be established and stored. These are found in variables with
|
rmeddis@0
|
120 % 'boundary' or 'bndry' in the name
|
rmeddis@0
|
121
|
rmeddis@0
|
122 %% OME ---
|
rmeddis@0
|
123 % external ear resonances
|
rmeddis@0
|
124 OMEexternalResonanceFilters=OMEParams.externalResonanceFilters;
|
rmeddis@0
|
125 [nOMEExtFilters c]=size(OMEexternalResonanceFilters);
|
rmeddis@0
|
126 % details of external (outer ear) resonances
|
rmeddis@0
|
127 OMEgaindBs=OMEexternalResonanceFilters(:,1);
|
rmeddis@0
|
128 OMEgainScalars=10.^(OMEgaindBs/20);
|
rmeddis@0
|
129 OMEfilterOrder=OMEexternalResonanceFilters(:,2);
|
rmeddis@0
|
130 OMElowerCutOff=OMEexternalResonanceFilters(:,3);
|
rmeddis@0
|
131 OMEupperCutOff=OMEexternalResonanceFilters(:,4);
|
rmeddis@0
|
132 % external resonance coefficients
|
rmeddis@0
|
133 ExtFilter_b=cell(nOMEExtFilters,1);
|
rmeddis@0
|
134 ExtFilter_a=cell(nOMEExtFilters,1);
|
rmeddis@0
|
135 for idx=1:nOMEExtFilters
|
rmeddis@0
|
136 Nyquist=sampleRate/2;
|
rmeddis@0
|
137 [b, a] = butter(OMEfilterOrder(idx), ...
|
rmeddis@0
|
138 [OMElowerCutOff(idx) OMEupperCutOff(idx)]...
|
rmeddis@0
|
139 /Nyquist);
|
rmeddis@0
|
140 ExtFilter_b{idx}=b;
|
rmeddis@0
|
141 ExtFilter_a{idx}=a;
|
rmeddis@0
|
142 end
|
rmeddis@0
|
143 OMEExtFilterBndry=cell(2,1);
|
rmeddis@0
|
144 OMEextEarPressure=zeros(1,signalLength); % pressure at tympanic membrane
|
rmeddis@0
|
145
|
rmeddis@0
|
146 % pressure to velocity conversion using smoothing filter (50 Hz cutoff)
|
rmeddis@0
|
147 tau=1/(2*pi*50);
|
rmeddis@0
|
148 a1=dt/tau-1; a0=1;
|
rmeddis@0
|
149 b0=1+ a1;
|
rmeddis@0
|
150 TMdisp_b=b0; TMdisp_a=[a0 a1];
|
rmeddis@0
|
151 % figure(9), freqz(TMdisp_b, TMdisp_a)
|
rmeddis@0
|
152 OME_TMdisplacementBndry=[];
|
rmeddis@0
|
153
|
rmeddis@0
|
154 % OME high pass (simulates poor low frequency stapes response)
|
rmeddis@0
|
155 OMEhighPassHighCutOff=OMEParams.OMEstapesLPcutoff;
|
rmeddis@0
|
156 Nyquist=sampleRate/2;
|
rmeddis@0
|
157 [stapesDisp_b,stapesDisp_a] = butter(1, OMEhighPassHighCutOff/Nyquist, 'high');
|
rmeddis@0
|
158 % figure(10), freqz(stapesDisp_b, stapesDisp_a)
|
rmeddis@0
|
159
|
rmeddis@0
|
160 OMEhighPassBndry=[];
|
rmeddis@0
|
161
|
rmeddis@0
|
162 % OMEampStapes might be reducdant (use OMEParams.stapesScalar)
|
rmeddis@0
|
163 stapesScalar= OMEParams.stapesScalar;
|
rmeddis@0
|
164
|
rmeddis@0
|
165 % Acoustic reflex
|
rmeddis@0
|
166 efferentDelayPts=round(OMEParams.ARdelay/dt);
|
rmeddis@0
|
167 % smoothing filter
|
rmeddis@0
|
168 % Nyquist=(1/ANdt)/2;
|
rmeddis@0
|
169 % [ARfilt_b,ARfilt_a] = butter(1, (1/(2*pi*OMEParams.ARtau))/Nyquist, 'low');
|
rmeddis@0
|
170 a1=dt/OMEParams.ARtau-1; a0=1;
|
rmeddis@0
|
171 b0=1+ a1;
|
rmeddis@0
|
172 ARfilt_b=b0; ARfilt_a=[a0 a1];
|
rmeddis@0
|
173
|
rmeddis@0
|
174 ARattenuation=ones(1,signalLength);
|
rmeddis@0
|
175 ARrateThreshold=OMEParams.ARrateThreshold; % may not be used
|
rmeddis@0
|
176 ARrateToAttenuationFactor=OMEParams.rateToAttenuationFactor;
|
rmeddis@0
|
177 ARrateToAttenuationFactorProb=OMEParams.rateToAttenuationFactorProb;
|
rmeddis@0
|
178 ARboundary=[];
|
rmeddis@0
|
179 ARboundaryProb=0;
|
rmeddis@0
|
180
|
rmeddis@0
|
181 % save complete OME record (stapes displacement)
|
rmeddis@0
|
182 OMEoutput=zeros(1,signalLength);
|
rmeddis@0
|
183 TMoutput=zeros(1,signalLength);
|
rmeddis@0
|
184
|
rmeddis@0
|
185 %% BM ---
|
rmeddis@0
|
186 % BM is represented as a list of locations identified by BF
|
rmeddis@0
|
187 DRNL_BFs=BFlist;
|
rmeddis@0
|
188 nBFs= length(DRNL_BFs);
|
rmeddis@0
|
189
|
rmeddis@0
|
190 % DRNLchannelParameters=DRNLParams.channelParameters;
|
rmeddis@0
|
191 DRNLresponse= zeros(nBFs, segmentLength);
|
rmeddis@0
|
192
|
rmeddis@0
|
193 MOCrateToAttenuationFactor=DRNLParams.rateToAttenuationFactor;
|
rmeddis@0
|
194 rateToAttenuationFactorProb=DRNLParams.rateToAttenuationFactorProb;
|
rmeddis@0
|
195 MOCrateThreshold=DRNLParams.MOCrateThreshold;
|
rmeddis@0
|
196
|
rmeddis@0
|
197 % smoothing filter for MOC
|
rmeddis@0
|
198 % Nyquist=(1/ANdt)/2;
|
rmeddis@0
|
199 % [MOCfilt_b,MOCfilt_a] = ...
|
rmeddis@0
|
200 % butter(1, (1/(2*pi*DRNLParams.MOCtau))/Nyquist, 'low');
|
rmeddis@0
|
201 % figure(10), freqz(stapesDisp_b, stapesDisp_a)
|
rmeddis@0
|
202 a1=dt/DRNLParams.MOCtau-1; a0=1;
|
rmeddis@0
|
203 b0=1+ a1;
|
rmeddis@0
|
204 MOCfilt_b=b0; MOCfilt_a=[a0 a1];
|
rmeddis@0
|
205 % figure(9), freqz(stapesDisp_b, stapesDisp_a)
|
rmeddis@0
|
206 MOCboundary=cell(nBFs,1);
|
rmeddis@0
|
207 MOCprobBoundary=cell(nBFs,1);
|
rmeddis@0
|
208
|
rmeddis@0
|
209 MOCattSegment=zeros(nBFs,reducedSegmentLength);
|
rmeddis@0
|
210 MOCattenuation=ones(nBFs,signalLength);
|
rmeddis@0
|
211
|
rmeddis@0
|
212 if DRNLParams.a>0
|
rmeddis@0
|
213 DRNLcompressionThreshold=10^((1/(1-DRNLParams.c))* ...
|
rmeddis@0
|
214 log10(DRNLParams.b/DRNLParams.a));
|
rmeddis@0
|
215 else
|
rmeddis@0
|
216 DRNLcompressionThreshold=inf;
|
rmeddis@0
|
217 end
|
rmeddis@0
|
218
|
rmeddis@0
|
219 DRNLlinearOrder= DRNLParams.linOrder;
|
rmeddis@0
|
220 DRNLnonlinearOrder= DRNLParams.nonlinOrder;
|
rmeddis@0
|
221
|
rmeddis@0
|
222 DRNLa=DRNLParams.a;
|
rmeddis@0
|
223 DRNLb=DRNLParams.b;
|
rmeddis@0
|
224 DRNLc=DRNLParams.c;
|
rmeddis@0
|
225 linGAIN=DRNLParams.g;
|
rmeddis@0
|
226 %
|
rmeddis@0
|
227 % gammatone filter coefficients for linear pathway
|
rmeddis@0
|
228 bw=DRNLParams.linBWs';
|
rmeddis@0
|
229 phi = 2 * pi * bw * dt;
|
rmeddis@0
|
230 cf=DRNLParams.linCFs';
|
rmeddis@0
|
231 theta = 2 * pi * cf * dt;
|
rmeddis@0
|
232 cos_theta = cos(theta);
|
rmeddis@0
|
233 sin_theta = sin(theta);
|
rmeddis@0
|
234 alpha = -exp(-phi).* cos_theta;
|
rmeddis@0
|
235 b0 = ones(nBFs,1);
|
rmeddis@0
|
236 b1 = 2 * alpha;
|
rmeddis@0
|
237 b2 = exp(-2 * phi);
|
rmeddis@0
|
238 z1 = (1 + alpha .* cos_theta) - (alpha .* sin_theta) * i;
|
rmeddis@0
|
239 z2 = (1 + b1 .* cos_theta) - (b1 .* sin_theta) * i;
|
rmeddis@0
|
240 z3 = (b2 .* cos(2 * theta)) - (b2 .* sin(2 * theta)) * i;
|
rmeddis@0
|
241 tf = (z2 + z3) ./ z1;
|
rmeddis@0
|
242 a0 = abs(tf);
|
rmeddis@0
|
243 a1 = alpha .* a0;
|
rmeddis@0
|
244 GTlin_a = [b0, b1, b2];
|
rmeddis@0
|
245 GTlin_b = [a0, a1];
|
rmeddis@0
|
246 GTlinOrder=DRNLlinearOrder;
|
rmeddis@0
|
247 GTlinBdry=cell(nBFs,GTlinOrder);
|
rmeddis@0
|
248
|
rmeddis@0
|
249 % nonlinear gammatone filter coefficients
|
rmeddis@0
|
250 bw=DRNLParams.nlBWs';
|
rmeddis@0
|
251 phi = 2 * pi * bw * dt;
|
rmeddis@0
|
252 cf=DRNLParams.nonlinCFs';
|
rmeddis@0
|
253 theta = 2 * pi * cf * dt;
|
rmeddis@0
|
254 cos_theta = cos(theta);
|
rmeddis@0
|
255 sin_theta = sin(theta);
|
rmeddis@0
|
256 alpha = -exp(-phi).* cos_theta;
|
rmeddis@0
|
257 b0 = ones(nBFs,1);
|
rmeddis@0
|
258 b1 = 2 * alpha;
|
rmeddis@0
|
259 b2 = exp(-2 * phi);
|
rmeddis@0
|
260 z1 = (1 + alpha .* cos_theta) - (alpha .* sin_theta) * i;
|
rmeddis@0
|
261 z2 = (1 + b1 .* cos_theta) - (b1 .* sin_theta) * i;
|
rmeddis@0
|
262 z3 = (b2 .* cos(2 * theta)) - (b2 .* sin(2 * theta)) * i;
|
rmeddis@0
|
263 tf = (z2 + z3) ./ z1;
|
rmeddis@0
|
264 a0 = abs(tf);
|
rmeddis@0
|
265 a1 = alpha .* a0;
|
rmeddis@0
|
266 GTnonlin_a = [b0, b1, b2];
|
rmeddis@0
|
267 GTnonlin_b = [a0, a1];
|
rmeddis@0
|
268 GTnonlinOrder=DRNLnonlinearOrder;
|
rmeddis@0
|
269 GTnonlinBdry1=cell(nBFs, GTnonlinOrder);
|
rmeddis@0
|
270 GTnonlinBdry2=cell(nBFs, GTnonlinOrder);
|
rmeddis@0
|
271
|
rmeddis@0
|
272 % complete BM record (BM displacement)
|
rmeddis@0
|
273 DRNLoutput=zeros(nBFs, signalLength);
|
rmeddis@0
|
274
|
rmeddis@0
|
275
|
rmeddis@0
|
276 %% IHC ---
|
rmeddis@0
|
277 % IHC cilia activity and receptor potential
|
rmeddis@0
|
278 % viscous coupling between BM and stereocilia displacement
|
rmeddis@0
|
279 % Nyquist=sampleRate/2;
|
rmeddis@0
|
280 % IHCcutoff=1/(2*pi*IHC_cilia_RPParams.tc);
|
rmeddis@0
|
281 % [IHCciliaFilter_b,IHCciliaFilter_a]=...
|
rmeddis@0
|
282 % butter(1, IHCcutoff/Nyquist, 'high');
|
rmeddis@0
|
283 a1=dt/IHC_cilia_RPParams.tc-1; a0=1;
|
rmeddis@0
|
284 b0=1+ a1;
|
rmeddis@0
|
285 % high pass (i.e. low pass reversed)
|
rmeddis@0
|
286 IHCciliaFilter_b=[a0 a1]; IHCciliaFilter_a=b0;
|
rmeddis@0
|
287 % figure(9), freqz(IHCciliaFilter_b, IHCciliaFilter_a)
|
rmeddis@0
|
288
|
rmeddis@0
|
289 IHCciliaBndry=cell(nBFs,1);
|
rmeddis@0
|
290
|
rmeddis@0
|
291 % IHC apical conductance (Boltzman function)
|
rmeddis@0
|
292 IHC_C= IHC_cilia_RPParams.C;
|
rmeddis@0
|
293 IHCu0= IHC_cilia_RPParams.u0;
|
rmeddis@0
|
294 IHCu1= IHC_cilia_RPParams.u1;
|
rmeddis@0
|
295 IHCs0= IHC_cilia_RPParams.s0;
|
rmeddis@0
|
296 IHCs1= IHC_cilia_RPParams.s1;
|
rmeddis@0
|
297 IHCGmax= IHC_cilia_RPParams.Gmax;
|
rmeddis@8
|
298 IHCGa= IHC_cilia_RPParams.Ga; % (leakage)
|
rmeddis@8
|
299
|
rmeddis@8
|
300 IHCGu0 = IHCGa+IHCGmax./(1+exp(IHCu0/IHCs0).*(1+exp(IHCu1/IHCs1)));
|
rmeddis@9
|
301 IHCrestingCiliaCond=IHCGu0;
|
rmeddis@0
|
302
|
rmeddis@0
|
303 % Receptor potential
|
rmeddis@0
|
304 IHC_Cab= IHC_cilia_RPParams.Cab;
|
rmeddis@0
|
305 IHC_Gk= IHC_cilia_RPParams.Gk;
|
rmeddis@0
|
306 IHC_Et= IHC_cilia_RPParams.Et;
|
rmeddis@0
|
307 IHC_Ek= IHC_cilia_RPParams.Ek;
|
rmeddis@0
|
308 IHC_Ekp= IHC_Ek+IHC_Et*IHC_cilia_RPParams.Rpc;
|
rmeddis@0
|
309
|
rmeddis@9
|
310 IHCrestingV= (IHC_Gk*IHC_Ekp+IHCGu0*IHC_Et)/(IHCGu0+IHC_Gk);
|
rmeddis@8
|
311
|
rmeddis@0
|
312 IHC_Vnow= IHCrestingV*ones(nBFs,1); % initial voltage
|
rmeddis@0
|
313 IHC_RP= zeros(nBFs,segmentLength);
|
rmeddis@0
|
314
|
rmeddis@0
|
315 % complete record of IHC receptor potential (V)
|
rmeddis@0
|
316 IHCciliaDisplacement= zeros(nBFs,segmentLength);
|
rmeddis@0
|
317 IHCoutput= zeros(nBFs,signalLength);
|
rmeddis@0
|
318 IHC_cilia_output= zeros(nBFs,signalLength);
|
rmeddis@0
|
319
|
rmeddis@0
|
320
|
rmeddis@0
|
321 %% pre-synapse ---
|
rmeddis@0
|
322 % Each BF is replicated using a different fiber type to make a 'channel'
|
rmeddis@0
|
323 % The number of channels is nBFs x nANfiberTypes
|
rmeddis@0
|
324 % Fiber types are specified in terms of tauCa
|
rmeddis@0
|
325 nANfiberTypes= length(IHCpreSynapseParams.tauCa);
|
rmeddis@0
|
326 tauCas= IHCpreSynapseParams.tauCa;
|
rmeddis@0
|
327 nChannels= nANfiberTypes*nBFs;
|
rmeddis@0
|
328 synapticCa= zeros(nChannels,segmentLength);
|
rmeddis@0
|
329
|
rmeddis@0
|
330 % Calcium control (more calcium, greater release rate)
|
rmeddis@0
|
331 ECa=IHCpreSynapseParams.ECa;
|
rmeddis@0
|
332 gamma=IHCpreSynapseParams.gamma;
|
rmeddis@0
|
333 beta=IHCpreSynapseParams.beta;
|
rmeddis@0
|
334 tauM=IHCpreSynapseParams.tauM;
|
rmeddis@0
|
335 mICa=zeros(nChannels,segmentLength);
|
rmeddis@0
|
336 GmaxCa=IHCpreSynapseParams.GmaxCa;
|
rmeddis@0
|
337 synapse_z= IHCpreSynapseParams.z;
|
rmeddis@0
|
338 synapse_power=IHCpreSynapseParams.power;
|
rmeddis@0
|
339
|
rmeddis@0
|
340 % tauCa vector is established across channels to allow vectorization
|
rmeddis@0
|
341 % (one tauCa per channel). Do not confuse with tauCas (one pre fiber type)
|
rmeddis@0
|
342 tauCa=repmat(tauCas, nBFs,1);
|
rmeddis@0
|
343 tauCa=reshape(tauCa, nChannels, 1);
|
rmeddis@0
|
344
|
rmeddis@0
|
345 % presynapse startup values (vectors, length:nChannels)
|
rmeddis@0
|
346 % proportion (0 - 1) of Ca channels open at IHCrestingV
|
rmeddis@0
|
347 mICaCurrent=((1+beta^-1 * exp(-gamma*IHCrestingV))^-1)...
|
rmeddis@0
|
348 *ones(nBFs*nANfiberTypes,1);
|
rmeddis@0
|
349 % corresponding startup currents
|
rmeddis@0
|
350 ICaCurrent= (GmaxCa*mICaCurrent.^3) * (IHCrestingV-ECa);
|
rmeddis@0
|
351 CaCurrent= ICaCurrent.*tauCa;
|
rmeddis@0
|
352
|
rmeddis@0
|
353 % vesicle release rate at startup (one per channel)
|
rmeddis@0
|
354 % kt0 is used only at initialisation
|
rmeddis@0
|
355 kt0= -synapse_z * CaCurrent.^synapse_power;
|
rmeddis@0
|
356
|
rmeddis@0
|
357
|
rmeddis@0
|
358 %% AN ---
|
rmeddis@0
|
359 % each row of the AN matrices represents one AN fiber
|
rmeddis@0
|
360 % The results computed either for probabiities *or* for spikes (not both)
|
rmeddis@0
|
361 % Spikes are necessary if CN and IC are to be computed
|
rmeddis@0
|
362 nFibersPerChannel= AN_IHCsynapseParams.numFibers;
|
rmeddis@0
|
363 nANfibers= nChannels*nFibersPerChannel;
|
rmeddis@0
|
364
|
rmeddis@0
|
365 y=AN_IHCsynapseParams.y;
|
rmeddis@0
|
366 l=AN_IHCsynapseParams.l;
|
rmeddis@0
|
367 x=AN_IHCsynapseParams.x;
|
rmeddis@0
|
368 r=AN_IHCsynapseParams.r;
|
rmeddis@0
|
369 M=round(AN_IHCsynapseParams.M);
|
rmeddis@0
|
370
|
rmeddis@0
|
371 % probability (NB initial 'P' on everything)
|
rmeddis@0
|
372 PAN_ydt = repmat(AN_IHCsynapseParams.y*dt, nChannels,1);
|
rmeddis@0
|
373 PAN_ldt = repmat(AN_IHCsynapseParams.l*dt, nChannels,1);
|
rmeddis@0
|
374 PAN_xdt = repmat(AN_IHCsynapseParams.x*dt, nChannels,1);
|
rmeddis@0
|
375 PAN_rdt = repmat(AN_IHCsynapseParams.r*dt, nChannels,1);
|
rmeddis@0
|
376 PAN_rdt_plus_ldt = PAN_rdt + PAN_ldt;
|
rmeddis@0
|
377 PAN_M=round(AN_IHCsynapseParams.M);
|
rmeddis@0
|
378
|
rmeddis@0
|
379 % compute starting values
|
rmeddis@0
|
380 Pcleft = kt0* y* M ./ (y*(l+r)+ kt0* l);
|
rmeddis@0
|
381 Pavailable = Pcleft*(l+r)./kt0;
|
rmeddis@0
|
382 Preprocess = Pcleft*r/x; % canbe fractional
|
rmeddis@0
|
383
|
rmeddis@0
|
384 ANprobability=zeros(nChannels,segmentLength);
|
rmeddis@0
|
385 ANprobRateOutput=zeros(nChannels,signalLength);
|
rmeddis@0
|
386 % special variables for monitoring synaptic cleft (specialists only)
|
rmeddis@0
|
387 savePavailableSeg=zeros(nChannels,segmentLength);
|
rmeddis@0
|
388 savePavailable=zeros(nChannels,signalLength);
|
rmeddis@0
|
389
|
rmeddis@0
|
390 % spikes % ! ! ! ! ! ! ! !
|
rmeddis@0
|
391 AN_refractory_period= AN_IHCsynapseParams.refractory_period;
|
rmeddis@0
|
392 lengthAbsRefractory= round(AN_refractory_period/ANdt);
|
rmeddis@0
|
393
|
rmeddis@0
|
394 AN_ydt= repmat(AN_IHCsynapseParams.y*ANdt, nANfibers,1);
|
rmeddis@0
|
395 AN_ldt= repmat(AN_IHCsynapseParams.l*ANdt, nANfibers,1);
|
rmeddis@0
|
396 AN_xdt= repmat(AN_IHCsynapseParams.x*ANdt, nANfibers,1);
|
rmeddis@0
|
397 AN_rdt= repmat(AN_IHCsynapseParams.r*ANdt, nANfibers,1);
|
rmeddis@0
|
398 AN_rdt_plus_ldt= AN_rdt + AN_ldt;
|
rmeddis@0
|
399 AN_M= round(AN_IHCsynapseParams.M);
|
rmeddis@0
|
400
|
rmeddis@0
|
401 % kt0 is initial release rate
|
rmeddis@0
|
402 % Establish as a vector (length=channel x number of fibers)
|
rmeddis@0
|
403 kt0= repmat(kt0', nFibersPerChannel, 1);
|
rmeddis@0
|
404 kt0=reshape(kt0, nANfibers,1);
|
rmeddis@0
|
405
|
rmeddis@0
|
406 % starting values for reservoirs
|
rmeddis@0
|
407 AN_cleft = kt0* y* M ./ (y*(l+r)+ kt0* l);
|
rmeddis@0
|
408 AN_available = round(AN_cleft*(l+r)./kt0); %must be integer
|
rmeddis@0
|
409 AN_reprocess = AN_cleft*r/x;
|
rmeddis@0
|
410
|
rmeddis@0
|
411 % output is in a logical array spikes = 1/ 0.
|
rmeddis@0
|
412 ANspikes= false(nANfibers,reducedSegmentLength);
|
rmeddis@0
|
413 ANoutput= false(nANfibers,reducedSignalLength);
|
rmeddis@0
|
414
|
rmeddis@0
|
415
|
rmeddis@0
|
416 %% CN (first brain stem nucleus - could be any subdivision of CN)
|
rmeddis@0
|
417 % Input to a CN neuorn is a random selection of AN fibers within a channel
|
rmeddis@0
|
418 % The number of AN fibers used is ANfibersFanInToCN
|
rmeddis@0
|
419 ANfibersFanInToCN=MacGregorMultiParams.fibersPerNeuron;
|
rmeddis@0
|
420 nCNneuronsPerChannel=MacGregorMultiParams.nNeuronsPerBF;
|
rmeddis@0
|
421 % CNtauGk (Potassium time constant) determines the rate of firing of
|
rmeddis@0
|
422 % the unit when driven hard by a DC input (not normally >350 sp/s)
|
rmeddis@0
|
423 CNtauGk=MacGregorMultiParams.tauGk;
|
rmeddis@0
|
424 ANavailableFibersPerChan=AN_IHCsynapseParams.numFibers;
|
rmeddis@0
|
425 nCNneurons=nCNneuronsPerChannel*nChannels;
|
rmeddis@0
|
426 % nCNneuronsPerFiberType= nCNneurons/nANfiberTypes;
|
rmeddis@0
|
427
|
rmeddis@0
|
428 CNmembranePotential=zeros(nCNneurons,reducedSegmentLength);
|
rmeddis@0
|
429
|
rmeddis@0
|
430 % establish which ANfibers (by name) feed into which CN nuerons
|
rmeddis@0
|
431 CNinputfiberLists=zeros(nChannels*nCNneuronsPerChannel, ANfibersFanInToCN);
|
rmeddis@0
|
432 unitNo=1;
|
rmeddis@0
|
433 for ch=1:nChannels
|
rmeddis@0
|
434 % Each channel contains a number of units =length(listOfFanInValues)
|
rmeddis@0
|
435 for idx=1:nCNneuronsPerChannel
|
rmeddis@0
|
436 fibersUsed=(ch-1)*ANavailableFibersPerChan + ...
|
rmeddis@0
|
437 ceil(rand(1,ANfibersFanInToCN)* ANavailableFibersPerChan);
|
rmeddis@0
|
438 CNinputfiberLists(unitNo,:)=fibersUsed;
|
rmeddis@0
|
439 unitNo=unitNo+1;
|
rmeddis@0
|
440 end
|
rmeddis@0
|
441 end
|
rmeddis@0
|
442
|
rmeddis@0
|
443 % input to CN units
|
rmeddis@0
|
444 AN_PSTH=zeros(nCNneurons,reducedSegmentLength);
|
rmeddis@0
|
445
|
rmeddis@0
|
446 % Generate CNalphaFunction function
|
rmeddis@0
|
447 % by which spikes are converted to post-synaptic currents
|
rmeddis@0
|
448 CNdendriteLPfreq= MacGregorMultiParams.dendriteLPfreq;
|
rmeddis@0
|
449 CNcurrentPerSpike=MacGregorMultiParams.currentPerSpike;
|
rmeddis@0
|
450 CNspikeToCurrentTau=1/(2*pi*CNdendriteLPfreq);
|
rmeddis@0
|
451 t=ANdt:ANdt:5*CNspikeToCurrentTau;
|
rmeddis@0
|
452 CNalphaFunction=...
|
rmeddis@0
|
453 (CNcurrentPerSpike/CNspikeToCurrentTau)*t.*exp(-t/CNspikeToCurrentTau);
|
rmeddis@0
|
454 % figure(98), plot(t,CNalphaFunction)
|
rmeddis@0
|
455 % working memory for implementing convolution
|
rmeddis@0
|
456 CNcurrentTemp=...
|
rmeddis@0
|
457 zeros(nCNneurons,reducedSegmentLength+length(CNalphaFunction)-1);
|
rmeddis@0
|
458 % trailing alphas are parts of humps carried forward to the next segment
|
rmeddis@0
|
459 CNtrailingAlphas=zeros(nCNneurons,length(CNalphaFunction));
|
rmeddis@0
|
460
|
rmeddis@0
|
461 CN_tauM=MacGregorMultiParams.tauM;
|
rmeddis@0
|
462 CN_tauTh=MacGregorMultiParams.tauTh;
|
rmeddis@0
|
463 CN_cap=MacGregorMultiParams.Cap;
|
rmeddis@0
|
464 CN_c=MacGregorMultiParams.c;
|
rmeddis@0
|
465 CN_b=MacGregorMultiParams.dGkSpike;
|
rmeddis@0
|
466 CN_Ek=MacGregorMultiParams.Ek;
|
rmeddis@0
|
467 CN_Eb= MacGregorMultiParams.Eb;
|
rmeddis@0
|
468 CN_Er=MacGregorMultiParams.Er;
|
rmeddis@0
|
469 CN_Th0= MacGregorMultiParams.Th0;
|
rmeddis@0
|
470 CN_E= zeros(nCNneurons,1);
|
rmeddis@0
|
471 CN_Gk= zeros(nCNneurons,1);
|
rmeddis@0
|
472 CN_Th= MacGregorMultiParams.Th0*ones(nCNneurons,1);
|
rmeddis@0
|
473 CN_Eb=CN_Eb.*ones(nCNneurons,1);
|
rmeddis@0
|
474 CN_Er=CN_Er.*ones(nCNneurons,1);
|
rmeddis@0
|
475 CNtimeSinceLastSpike=zeros(nCNneurons,1);
|
rmeddis@0
|
476 % tauGk is the main distinction between neurons
|
rmeddis@0
|
477 % in fact they are all the same in the standard model
|
rmeddis@0
|
478 tauGk=repmat(CNtauGk,nChannels*nCNneuronsPerChannel,1);
|
rmeddis@0
|
479
|
rmeddis@0
|
480 CN_PSTH=zeros(nChannels,reducedSegmentLength);
|
rmeddis@0
|
481 CNoutput=false(nCNneurons,reducedSignalLength);
|
rmeddis@0
|
482
|
rmeddis@0
|
483
|
rmeddis@0
|
484 %% MacGregor (IC - second nucleus) --------
|
rmeddis@0
|
485 nICcells=nChannels; % one cell per channel
|
rmeddis@0
|
486
|
rmeddis@0
|
487 ICspikeWidth=0.00015; % this may need revisiting
|
rmeddis@0
|
488 epochsPerSpike=round(ICspikeWidth/ANdt);
|
rmeddis@0
|
489 if epochsPerSpike<1
|
rmeddis@0
|
490 error(['MacGregorMulti: sample rate too low to support ' ...
|
rmeddis@0
|
491 num2str(ICspikeWidth*1e6) ' microsec spikes']);
|
rmeddis@0
|
492 end
|
rmeddis@0
|
493
|
rmeddis@0
|
494 % short names
|
rmeddis@0
|
495 IC_tauM=MacGregorParams.tauM;
|
rmeddis@0
|
496 IC_tauGk=MacGregorParams.tauGk;
|
rmeddis@0
|
497 IC_tauTh=MacGregorParams.tauTh;
|
rmeddis@0
|
498 IC_cap=MacGregorParams.Cap;
|
rmeddis@0
|
499 IC_c=MacGregorParams.c;
|
rmeddis@0
|
500 IC_b=MacGregorParams.dGkSpike;
|
rmeddis@0
|
501 IC_Th0=MacGregorParams.Th0;
|
rmeddis@0
|
502 IC_Ek=MacGregorParams.Ek;
|
rmeddis@0
|
503 IC_Eb= MacGregorParams.Eb;
|
rmeddis@0
|
504 IC_Er=MacGregorParams.Er;
|
rmeddis@0
|
505
|
rmeddis@0
|
506 IC_E=zeros(nICcells,1);
|
rmeddis@0
|
507 IC_Gk=zeros(nICcells,1);
|
rmeddis@0
|
508 IC_Th=IC_Th0*ones(nICcells,1);
|
rmeddis@0
|
509
|
rmeddis@0
|
510 % Dendritic filtering, all spikes are replaced by CNalphaFunction functions
|
rmeddis@0
|
511 ICdendriteLPfreq= MacGregorParams.dendriteLPfreq;
|
rmeddis@0
|
512 ICcurrentPerSpike=MacGregorParams.currentPerSpike;
|
rmeddis@0
|
513 ICspikeToCurrentTau=1/(2*pi*ICdendriteLPfreq);
|
rmeddis@0
|
514 t=ANdt:ANdt:3*ICspikeToCurrentTau;
|
rmeddis@0
|
515 IC_CNalphaFunction= (ICcurrentPerSpike / ...
|
rmeddis@0
|
516 ICspikeToCurrentTau)*t.*exp(-t / ICspikeToCurrentTau);
|
rmeddis@0
|
517 % figure(98), plot(t,IC_CNalphaFunction)
|
rmeddis@0
|
518
|
rmeddis@0
|
519 % working space for implementing alpha function
|
rmeddis@0
|
520 ICcurrentTemp=...
|
rmeddis@0
|
521 zeros(nICcells,reducedSegmentLength+length(IC_CNalphaFunction)-1);
|
rmeddis@0
|
522 ICtrailingAlphas=zeros(nICcells, length(IC_CNalphaFunction));
|
rmeddis@0
|
523
|
rmeddis@0
|
524 ICfiberTypeRates=zeros(nANfiberTypes,reducedSignalLength);
|
rmeddis@0
|
525 ICoutput=false(nChannels,reducedSignalLength);
|
rmeddis@0
|
526
|
rmeddis@0
|
527 ICmembranePotential=zeros(nICcells,reducedSegmentLength);
|
rmeddis@0
|
528 ICmembraneOutput=zeros(nICcells,signalLength);
|
rmeddis@0
|
529
|
rmeddis@0
|
530
|
rmeddis@0
|
531 %% Main program %% %% %% %% %% %% %% %% %% %% %% %% %% %%
|
rmeddis@0
|
532
|
rmeddis@0
|
533 % Compute the entire model for each segment
|
rmeddis@0
|
534 segmentStartPTR=1;
|
rmeddis@0
|
535 reducedSegmentPTR=1; % when sampling rate is reduced
|
rmeddis@0
|
536 while segmentStartPTR<signalLength
|
rmeddis@0
|
537 segmentEndPTR=segmentStartPTR+segmentLength-1;
|
rmeddis@0
|
538 % shorter segments after speed up.
|
rmeddis@0
|
539 shorterSegmentEndPTR=reducedSegmentPTR+reducedSegmentLength-1;
|
rmeddis@0
|
540
|
rmeddis@0
|
541 iputPressureSegment=inputSignal...
|
rmeddis@0
|
542 (:,segmentStartPTR:segmentStartPTR+segmentLength-1);
|
rmeddis@0
|
543
|
rmeddis@0
|
544 % segment debugging plots
|
rmeddis@0
|
545 % figure(98)
|
rmeddis@0
|
546 % plot(segmentTime,iputPressureSegment), title('signalSegment')
|
rmeddis@0
|
547
|
rmeddis@0
|
548
|
rmeddis@0
|
549 % OME ----------------------
|
rmeddis@0
|
550
|
rmeddis@0
|
551 % OME Stage 1: external resonances. Add to inputSignal pressure wave
|
rmeddis@0
|
552 y=iputPressureSegment;
|
rmeddis@0
|
553 for n=1:nOMEExtFilters
|
rmeddis@0
|
554 % any number of resonances can be used
|
rmeddis@0
|
555 [x OMEExtFilterBndry{n}] = ...
|
rmeddis@0
|
556 filter(ExtFilter_b{n},ExtFilter_a{n},...
|
rmeddis@0
|
557 iputPressureSegment, OMEExtFilterBndry{n});
|
rmeddis@0
|
558 x= x* OMEgainScalars(n);
|
rmeddis@0
|
559 % This is a parallel resonance so add it
|
rmeddis@0
|
560 y=y+x;
|
rmeddis@0
|
561 end
|
rmeddis@0
|
562 iputPressureSegment=y;
|
rmeddis@0
|
563 OMEextEarPressure(segmentStartPTR:segmentEndPTR)= iputPressureSegment;
|
rmeddis@0
|
564
|
rmeddis@0
|
565 % OME stage 2: convert input pressure (velocity) to
|
rmeddis@0
|
566 % tympanic membrane(TM) displacement using low pass filter
|
rmeddis@0
|
567 [TMdisplacementSegment OME_TMdisplacementBndry] = ...
|
rmeddis@0
|
568 filter(TMdisp_b,TMdisp_a,iputPressureSegment, ...
|
rmeddis@0
|
569 OME_TMdisplacementBndry);
|
rmeddis@0
|
570 % and save it
|
rmeddis@0
|
571 TMoutput(segmentStartPTR:segmentEndPTR)= TMdisplacementSegment;
|
rmeddis@0
|
572
|
rmeddis@0
|
573 % OME stage 3: middle ear high pass effect to simulate stapes inertia
|
rmeddis@0
|
574 [stapesDisplacement OMEhighPassBndry] = ...
|
rmeddis@0
|
575 filter(stapesDisp_b,stapesDisp_a,TMdisplacementSegment, ...
|
rmeddis@0
|
576 OMEhighPassBndry);
|
rmeddis@0
|
577
|
rmeddis@0
|
578 % OME stage 4: apply stapes scalar
|
rmeddis@0
|
579 stapesDisplacement=stapesDisplacement*stapesScalar;
|
rmeddis@0
|
580
|
rmeddis@0
|
581 % OME stage 5: acoustic reflex stapes attenuation
|
rmeddis@0
|
582 % Attenuate the TM response using feedback from LSR fiber activity
|
rmeddis@0
|
583 if segmentStartPTR>efferentDelayPts
|
rmeddis@0
|
584 stapesDisplacement= stapesDisplacement.*...
|
rmeddis@0
|
585 ARattenuation(segmentStartPTR-efferentDelayPts:...
|
rmeddis@0
|
586 segmentEndPTR-efferentDelayPts);
|
rmeddis@0
|
587 end
|
rmeddis@0
|
588
|
rmeddis@0
|
589 % segment debugging plots
|
rmeddis@0
|
590 % figure(98)
|
rmeddis@0
|
591 % plot(segmentTime, stapesDisplacement), title ('stapesDisplacement')
|
rmeddis@0
|
592
|
rmeddis@0
|
593 % and save
|
rmeddis@0
|
594 OMEoutput(segmentStartPTR:segmentEndPTR)= stapesDisplacement;
|
rmeddis@0
|
595
|
rmeddis@0
|
596
|
rmeddis@0
|
597 %% BM ------------------------------
|
rmeddis@0
|
598 % Each location is computed separately
|
rmeddis@0
|
599 for BFno=1:nBFs
|
rmeddis@0
|
600
|
rmeddis@0
|
601 % *linear* path
|
rmeddis@0
|
602 linOutput = stapesDisplacement * linGAIN; % linear gain
|
rmeddis@0
|
603 for order = 1 : GTlinOrder
|
rmeddis@0
|
604 [linOutput GTlinBdry{BFno,order}] = ...
|
rmeddis@0
|
605 filter(GTlin_b(BFno,:), GTlin_a(BFno,:), linOutput, GTlinBdry{BFno,order});
|
rmeddis@0
|
606 end
|
rmeddis@0
|
607
|
rmeddis@0
|
608 % *nonLinear* path
|
rmeddis@0
|
609 % efferent attenuation (0 <> 1)
|
rmeddis@0
|
610 if segmentStartPTR>efferentDelayPts
|
rmeddis@0
|
611 MOC=MOCattenuation(BFno, segmentStartPTR-efferentDelayPts:...
|
rmeddis@0
|
612 segmentEndPTR-efferentDelayPts);
|
rmeddis@0
|
613 else % no MOC available yet
|
rmeddis@0
|
614 MOC=ones(1, segmentLength);
|
rmeddis@0
|
615 end
|
rmeddis@0
|
616
|
rmeddis@0
|
617 % first gammatone filter
|
rmeddis@0
|
618 for order = 1 : GTnonlinOrder
|
rmeddis@0
|
619 [nonlinOutput GTnonlinBdry1{BFno,order}] = ...
|
rmeddis@0
|
620 filter(GTnonlin_b(BFno,:), GTnonlin_a(BFno,:), ...
|
rmeddis@0
|
621 stapesDisplacement, GTnonlinBdry1{BFno,order});
|
rmeddis@0
|
622 end
|
rmeddis@0
|
623
|
rmeddis@0
|
624 % broken stick instantaneous compression
|
rmeddis@0
|
625 % nonlinear gain is weakend by MOC before applied to BM response
|
rmeddis@0
|
626 y= nonlinOutput.*(MOC* DRNLa); % linear section.
|
rmeddis@0
|
627 % compress those parts of the signal above the compression
|
rmeddis@0
|
628 % threshold
|
rmeddis@0
|
629 abs_x = abs(nonlinOutput);
|
rmeddis@0
|
630 idx=find(abs_x>DRNLcompressionThreshold);
|
rmeddis@0
|
631 if ~isempty(idx)>0
|
rmeddis@0
|
632 y(idx)=sign(nonlinOutput(idx)).*...
|
rmeddis@0
|
633 (DRNLb*abs_x(idx).^DRNLc);
|
rmeddis@0
|
634 end
|
rmeddis@0
|
635 nonlinOutput=y;
|
rmeddis@0
|
636
|
rmeddis@0
|
637 % second filter removes distortion products
|
rmeddis@0
|
638 for order = 1 : GTnonlinOrder
|
rmeddis@0
|
639 [ nonlinOutput GTnonlinBdry2{BFno,order}] = ...
|
rmeddis@0
|
640 filter(GTnonlin_b(BFno,:), GTnonlin_a(BFno,:), nonlinOutput, GTnonlinBdry2{BFno,order});
|
rmeddis@0
|
641 end
|
rmeddis@0
|
642
|
rmeddis@0
|
643 % combine the two paths to give the DRNL displacement
|
rmeddis@0
|
644 DRNLresponse(BFno,:)=linOutput+nonlinOutput;
|
rmeddis@0
|
645 end % BF
|
rmeddis@0
|
646
|
rmeddis@0
|
647 % segment debugging plots
|
rmeddis@0
|
648 % figure(98)
|
rmeddis@0
|
649 % if size(DRNLresponse,1)>3
|
rmeddis@0
|
650 % imagesc(DRNLresponse) % matrix display
|
rmeddis@0
|
651 % title('DRNLresponse'); % single or double channel response
|
rmeddis@0
|
652 % else
|
rmeddis@0
|
653 % plot(segmentTime, DRNLresponse)
|
rmeddis@0
|
654 % end
|
rmeddis@0
|
655
|
rmeddis@0
|
656 % and save it
|
rmeddis@0
|
657 DRNLoutput(:, segmentStartPTR:segmentEndPTR)= DRNLresponse;
|
rmeddis@0
|
658
|
rmeddis@0
|
659
|
rmeddis@0
|
660 %% IHC ------------------------------------
|
rmeddis@0
|
661 % BM displacement to IHCciliaDisplacement is a high-pass filter
|
rmeddis@0
|
662 % because of viscous coupling
|
rmeddis@0
|
663 for idx=1:nBFs
|
rmeddis@0
|
664 [IHCciliaDisplacement(idx,:) IHCciliaBndry{idx}] = ...
|
rmeddis@0
|
665 filter(IHCciliaFilter_b,IHCciliaFilter_a, ...
|
rmeddis@0
|
666 DRNLresponse(idx,:), IHCciliaBndry{idx});
|
rmeddis@0
|
667 end
|
rmeddis@0
|
668
|
rmeddis@0
|
669 % apply scalar
|
rmeddis@0
|
670 IHCciliaDisplacement=IHCciliaDisplacement* IHC_C;
|
rmeddis@0
|
671
|
rmeddis@0
|
672 % and save it
|
rmeddis@0
|
673 IHC_cilia_output(:,segmentStartPTR:segmentStartPTR+segmentLength-1)=...
|
rmeddis@0
|
674 IHCciliaDisplacement;
|
rmeddis@0
|
675
|
rmeddis@0
|
676 % compute apical conductance
|
rmeddis@9
|
677 G=IHCGmax./(1+exp(-(IHCciliaDisplacement-IHCu0)/IHCs0).*...
|
rmeddis@0
|
678 (1+exp(-(IHCciliaDisplacement-IHCu1)/IHCs1)));
|
rmeddis@9
|
679 Gu=G + IHCGa;
|
rmeddis@0
|
680
|
rmeddis@0
|
681 % Compute receptor potential
|
rmeddis@0
|
682 for idx=1:segmentLength
|
rmeddis@0
|
683 IHC_Vnow=IHC_Vnow+ (-Gu(:, idx).*(IHC_Vnow-IHC_Et)-...
|
rmeddis@0
|
684 IHC_Gk*(IHC_Vnow-IHC_Ekp))* dt/IHC_Cab;
|
rmeddis@0
|
685 IHC_RP(:,idx)=IHC_Vnow;
|
rmeddis@0
|
686 end
|
rmeddis@0
|
687
|
rmeddis@0
|
688 % segment debugging plots
|
rmeddis@0
|
689 % if size(IHC_RP,1)>3
|
rmeddis@0
|
690 % surf(IHC_RP), shading interp, title('IHC_RP')
|
rmeddis@0
|
691 % else
|
rmeddis@0
|
692 % plot(segmentTime, IHC_RP)
|
rmeddis@0
|
693 % end
|
rmeddis@0
|
694
|
rmeddis@0
|
695 % and save it
|
rmeddis@0
|
696 IHCoutput(:, segmentStartPTR:segmentStartPTR+segmentLength-1)=IHC_RP;
|
rmeddis@0
|
697
|
rmeddis@0
|
698
|
rmeddis@0
|
699 %% synapse -----------------------------
|
rmeddis@0
|
700 % Compute the vesicle release rate for each fiber type at each BF
|
rmeddis@0
|
701 % replicate IHC_RP for each fiber type
|
rmeddis@0
|
702 Vsynapse=repmat(IHC_RP, nANfiberTypes,1);
|
rmeddis@0
|
703
|
rmeddis@0
|
704 % look-up table of target fraction channels open for a given IHC_RP
|
rmeddis@0
|
705 mICaINF= 1./( 1 + exp(-gamma * Vsynapse) /beta);
|
rmeddis@0
|
706 % fraction of channel open - apply time constant
|
rmeddis@0
|
707 for idx=1:segmentLength
|
rmeddis@0
|
708 % mICaINF is the current 'target' value of mICa
|
rmeddis@0
|
709 mICaCurrent=mICaCurrent+(mICaINF(:,idx)-mICaCurrent)*dt./tauM;
|
rmeddis@0
|
710 mICa(:,idx)=mICaCurrent;
|
rmeddis@0
|
711 end
|
rmeddis@0
|
712
|
rmeddis@0
|
713 ICa= (GmaxCa* mICa.^3) .* (Vsynapse- ECa);
|
rmeddis@0
|
714
|
rmeddis@0
|
715 for idx=1:segmentLength
|
rmeddis@0
|
716 CaCurrent=CaCurrent + ICa(:,idx)*dt - CaCurrent*dt./tauCa;
|
rmeddis@0
|
717 synapticCa(:,idx)=CaCurrent;
|
rmeddis@0
|
718 end
|
rmeddis@0
|
719 synapticCa=-synapticCa; % treat IHCpreSynapseParams as positive substance
|
rmeddis@0
|
720
|
rmeddis@0
|
721 % NB vesicleReleaseRate is /s and is independent of dt
|
rmeddis@0
|
722 vesicleReleaseRate = synapse_z * synapticCa.^synapse_power; % rate
|
rmeddis@0
|
723
|
rmeddis@0
|
724 % segment debugging plots
|
rmeddis@0
|
725 % if size(vesicleReleaseRate,1)>3
|
rmeddis@0
|
726 % surf(vesicleReleaseRate), shading interp, title('vesicleReleaseRate')
|
rmeddis@0
|
727 % else
|
rmeddis@0
|
728 % plot(segmentTime, vesicleReleaseRate)
|
rmeddis@0
|
729 % end
|
rmeddis@0
|
730
|
rmeddis@0
|
731
|
rmeddis@0
|
732 %% AN
|
rmeddis@0
|
733 switch AN_spikesOrProbability
|
rmeddis@0
|
734 case 'probability'
|
rmeddis@0
|
735 % No refractory effect is applied
|
rmeddis@0
|
736 for t = 1:segmentLength;
|
rmeddis@0
|
737 M_Pq=PAN_M-Pavailable;
|
rmeddis@0
|
738 M_Pq(M_Pq<0)=0;
|
rmeddis@0
|
739 Preplenish = M_Pq .* PAN_ydt;
|
rmeddis@0
|
740 Pejected = Pavailable.* vesicleReleaseRate(:,t)*dt;
|
rmeddis@0
|
741 Preprocessed = M_Pq.*Preprocess.* PAN_xdt;
|
rmeddis@0
|
742
|
rmeddis@0
|
743 ANprobability(:,t)= min(Pejected,1);
|
rmeddis@0
|
744 reuptakeandlost= PAN_rdt_plus_ldt .* Pcleft;
|
rmeddis@0
|
745 reuptake= PAN_rdt.* Pcleft;
|
rmeddis@0
|
746
|
rmeddis@0
|
747 Pavailable= Pavailable+ Preplenish- Pejected+ Preprocessed;
|
rmeddis@0
|
748 Pcleft= Pcleft + Pejected - reuptakeandlost;
|
rmeddis@0
|
749 Preprocess= Preprocess + reuptake - Preprocessed;
|
rmeddis@0
|
750 Pavailable(Pavailable<0)=0;
|
rmeddis@0
|
751 savePavailableSeg(:,t)=Pavailable; % synapse tracking
|
rmeddis@0
|
752 end
|
rmeddis@0
|
753 % and save it as *rate*
|
rmeddis@0
|
754 ANrate=ANprobability/dt;
|
rmeddis@0
|
755 ANprobRateOutput(:, segmentStartPTR:...
|
rmeddis@0
|
756 segmentStartPTR+segmentLength-1)= ANrate;
|
rmeddis@0
|
757 % monitor synapse contents (only sometimes used)
|
rmeddis@0
|
758 savePavailable(:, segmentStartPTR:segmentStartPTR+segmentLength-1)=...
|
rmeddis@0
|
759 savePavailableSeg;
|
rmeddis@0
|
760
|
rmeddis@0
|
761 % Estimate efferent effects. ARattenuation (0 <> 1)
|
rmeddis@0
|
762 % acoustic reflex
|
rmeddis@0
|
763 ARAttSeg=mean(ANrate(1:nBFs,:),1); %LSR channels are 1:nBF
|
rmeddis@0
|
764 % smooth
|
rmeddis@0
|
765 [ARAttSeg, ARboundaryProb] = ...
|
rmeddis@0
|
766 filter(ARfilt_b, ARfilt_a, ARAttSeg, ARboundaryProb);
|
rmeddis@0
|
767 ARAttSeg=ARAttSeg-ARrateThreshold;
|
rmeddis@0
|
768 ARAttSeg(ARAttSeg<0)=0; % prevent negative strengths
|
rmeddis@0
|
769 ARattenuation(segmentStartPTR:segmentEndPTR)=...
|
rmeddis@0
|
770 (1-ARrateToAttenuationFactorProb.* ARAttSeg);
|
rmeddis@0
|
771
|
rmeddis@0
|
772 % MOC attenuation
|
rmeddis@0
|
773 % within-channel HSR response only
|
rmeddis@0
|
774 HSRbegins=nBFs*(nANfiberTypes-1)+1;
|
rmeddis@0
|
775 rates=ANrate(HSRbegins:end,:);
|
rmeddis@0
|
776 for idx=1:nBFs
|
rmeddis@0
|
777 [smoothedRates, MOCprobBoundary{idx}] = ...
|
rmeddis@0
|
778 filter(MOCfilt_b, MOCfilt_a, rates(idx,:), ...
|
rmeddis@0
|
779 MOCprobBoundary{idx});
|
rmeddis@0
|
780 smoothedRates=smoothedRates-MOCrateThreshold;
|
rmeddis@0
|
781 smoothedRates(smoothedRates<0)=0;
|
rmeddis@0
|
782 MOCattenuation(idx,segmentStartPTR:segmentEndPTR)= ...
|
rmeddis@0
|
783 (1- smoothedRates* rateToAttenuationFactorProb);
|
rmeddis@0
|
784 end
|
rmeddis@0
|
785 MOCattenuation(MOCattenuation<0)=0.001;
|
rmeddis@0
|
786
|
rmeddis@0
|
787
|
rmeddis@0
|
788 case 'spikes'
|
rmeddis@0
|
789 ANtimeCount=0;
|
rmeddis@0
|
790 % implement speed upt
|
rmeddis@0
|
791 for t = ANspeedUpFactor:ANspeedUpFactor:segmentLength;
|
rmeddis@0
|
792 ANtimeCount=ANtimeCount+1;
|
rmeddis@0
|
793 % convert release rate to probabilities
|
rmeddis@0
|
794 releaseProb=vesicleReleaseRate(:,t)*ANdt;
|
rmeddis@0
|
795 % releaseProb is the release probability per channel
|
rmeddis@0
|
796 % but each channel has many synapses
|
rmeddis@0
|
797 releaseProb=repmat(releaseProb',nFibersPerChannel,1);
|
rmeddis@0
|
798 releaseProb=reshape(releaseProb, nFibersPerChannel*nChannels,1);
|
rmeddis@0
|
799
|
rmeddis@0
|
800 % AN_available=round(AN_available); % vesicles must be integer, (?needed)
|
rmeddis@0
|
801 M_q=AN_M- AN_available; % number of missing vesicles
|
rmeddis@0
|
802 M_q(M_q<0)= 0; % cannot be less than 0
|
rmeddis@0
|
803
|
rmeddis@0
|
804 % AN_N1 converts probability to discrete events
|
rmeddis@0
|
805 % it considers each event that might occur
|
rmeddis@0
|
806 % (how many vesicles might be released)
|
rmeddis@0
|
807 % and returns a count of how many were released
|
rmeddis@0
|
808
|
rmeddis@0
|
809 % slow line
|
rmeddis@0
|
810 % probabilities= 1-(1-releaseProb).^AN_available;
|
rmeddis@0
|
811 probabilities= 1-intpow((1-releaseProb), AN_available);
|
rmeddis@0
|
812 ejected= probabilities> rand(length(AN_available),1);
|
rmeddis@0
|
813
|
rmeddis@0
|
814 reuptakeandlost = AN_rdt_plus_ldt .* AN_cleft;
|
rmeddis@0
|
815 reuptake = AN_rdt.* AN_cleft;
|
rmeddis@0
|
816
|
rmeddis@0
|
817 % slow line
|
rmeddis@0
|
818 % probabilities= 1-(1-AN_reprocess.*AN_xdt).^M_q;
|
rmeddis@0
|
819 probabilities= 1-intpow((1-AN_reprocess.*AN_xdt), M_q);
|
rmeddis@0
|
820 reprocessed= probabilities>rand(length(M_q),1);
|
rmeddis@0
|
821
|
rmeddis@0
|
822 % slow line
|
rmeddis@0
|
823 % probabilities= 1-(1-AN_ydt).^M_q;
|
rmeddis@0
|
824 probabilities= 1-intpow((1-AN_ydt), M_q);
|
rmeddis@0
|
825
|
rmeddis@0
|
826 replenish= probabilities>rand(length(M_q),1);
|
rmeddis@0
|
827
|
rmeddis@0
|
828 AN_available = AN_available + replenish - ejected ...
|
rmeddis@0
|
829 + reprocessed;
|
rmeddis@0
|
830 AN_cleft = AN_cleft + ejected - reuptakeandlost;
|
rmeddis@0
|
831 AN_reprocess = AN_reprocess + reuptake - reprocessed;
|
rmeddis@0
|
832
|
rmeddis@0
|
833 % ANspikes is logical record of vesicle release events>0
|
rmeddis@0
|
834 ANspikes(:, ANtimeCount)= ejected;
|
rmeddis@0
|
835 end % t
|
rmeddis@0
|
836
|
rmeddis@0
|
837 % zero any events that are preceded by release events ...
|
rmeddis@0
|
838 % within the refractory period
|
rmeddis@0
|
839 % The refractory period consist of two periods
|
rmeddis@0
|
840 % 1) the absolute period where no spikes occur
|
rmeddis@0
|
841 % 2) a relative period where a spike may occur. This relative
|
rmeddis@0
|
842 % period is realised as a variable length interval
|
rmeddis@0
|
843 % where the length is chosen at random
|
rmeddis@0
|
844 % (esentially a linear ramp up)
|
rmeddis@0
|
845
|
rmeddis@0
|
846 % Andreas has a fix for this
|
rmeddis@0
|
847 for t = 1:ANtimeCount-2*lengthAbsRefractory;
|
rmeddis@0
|
848 % identify all spikes across fiber array at time (t)
|
rmeddis@0
|
849 % idx is a list of channels where spikes occurred
|
rmeddis@0
|
850 % ?? try sparse matrices?
|
rmeddis@0
|
851 idx=find(ANspikes(:,t));
|
rmeddis@0
|
852 for j=idx % consider each spike
|
rmeddis@0
|
853 % specify variable refractory period
|
rmeddis@0
|
854 % between abs and 2*abs refractory period
|
rmeddis@0
|
855 nPointsRefractory=lengthAbsRefractory+...
|
rmeddis@0
|
856 round(rand*lengthAbsRefractory);
|
rmeddis@0
|
857 % disable spike potential for refractory period
|
rmeddis@0
|
858 % set all values in this range to 0
|
rmeddis@0
|
859 ANspikes(j,t+1:t+nPointsRefractory)=0;
|
rmeddis@0
|
860 end
|
rmeddis@0
|
861 end %t
|
rmeddis@0
|
862
|
rmeddis@0
|
863 % segment debugging
|
rmeddis@0
|
864 % plotInstructions.figureNo=98;
|
rmeddis@0
|
865 % plotInstructions.displaydt=ANdt;
|
rmeddis@0
|
866 % plotInstructions.numPlots=1;
|
rmeddis@0
|
867 % plotInstructions.subPlotNo=1;
|
rmeddis@0
|
868 % UTIL_plotMatrix(ANspikes, plotInstructions);
|
rmeddis@0
|
869
|
rmeddis@0
|
870 % and save it. NB, AN is now on 'speedUp' time
|
rmeddis@0
|
871 ANoutput(:, reducedSegmentPTR: shorterSegmentEndPTR)=ANspikes;
|
rmeddis@0
|
872
|
rmeddis@0
|
873
|
rmeddis@0
|
874 %% CN Macgregor first neucleus -------------------------------
|
rmeddis@0
|
875 % input is from AN so ANdt is used throughout
|
rmeddis@0
|
876 % Each CNneuron has a unique set of input fibers selected
|
rmeddis@0
|
877 % at random from the available AN fibers (CNinputfiberLists)
|
rmeddis@0
|
878
|
rmeddis@0
|
879 % Create the dendritic current for that neuron
|
rmeddis@0
|
880 % First get input spikes to this neuron
|
rmeddis@0
|
881 synapseNo=1;
|
rmeddis@0
|
882 for ch=1:nChannels
|
rmeddis@0
|
883 for idx=1:nCNneuronsPerChannel
|
rmeddis@0
|
884 % determine candidate fibers for this unit
|
rmeddis@0
|
885 fibersUsed=CNinputfiberLists(synapseNo,:);
|
rmeddis@0
|
886 % ANpsth has a bin width of dt
|
rmeddis@0
|
887 % (just a simple sum across fibers)
|
rmeddis@0
|
888 AN_PSTH(synapseNo,:) = ...
|
rmeddis@0
|
889 sum(ANspikes(fibersUsed,:), 1);
|
rmeddis@0
|
890 synapseNo=synapseNo+1;
|
rmeddis@0
|
891 end
|
rmeddis@0
|
892 end
|
rmeddis@0
|
893
|
rmeddis@0
|
894 % One alpha function per spike
|
rmeddis@0
|
895 [alphaRows alphaCols]=size(CNtrailingAlphas);
|
rmeddis@0
|
896
|
rmeddis@0
|
897 for unitNo=1:nCNneurons
|
rmeddis@0
|
898 CNcurrentTemp(unitNo,:)= ...
|
rmeddis@0
|
899 conv(AN_PSTH(unitNo,:),CNalphaFunction);
|
rmeddis@0
|
900 end
|
rmeddis@0
|
901 % add post-synaptic current left over from previous segment
|
rmeddis@0
|
902 CNcurrentTemp(:,1:alphaCols)=...
|
rmeddis@0
|
903 CNcurrentTemp(:,1:alphaCols)+ CNtrailingAlphas;
|
rmeddis@0
|
904
|
rmeddis@0
|
905 % take post-synaptic current for this segment
|
rmeddis@0
|
906 CNcurrentInput= CNcurrentTemp(:, 1:reducedSegmentLength);
|
rmeddis@0
|
907
|
rmeddis@0
|
908 % trailingalphas are the ends of the alpha functions that
|
rmeddis@0
|
909 % spill over into the next segment
|
rmeddis@0
|
910 CNtrailingAlphas= ...
|
rmeddis@0
|
911 CNcurrentTemp(:, reducedSegmentLength+1:end);
|
rmeddis@0
|
912
|
rmeddis@0
|
913 if CN_c>0
|
rmeddis@0
|
914 % variable threshold condition (slow)
|
rmeddis@0
|
915 for t=1:reducedSegmentLength
|
rmeddis@0
|
916 CNtimeSinceLastSpike=CNtimeSinceLastSpike-dts;
|
rmeddis@0
|
917 s=CN_E>CN_Th & CNtimeSinceLastSpike<0 ;
|
rmeddis@0
|
918 CNtimeSinceLastSpike(s)=0.0005; % 0.5 ms for sodium spike
|
rmeddis@0
|
919 dE =(-CN_E/CN_tauM + ...
|
rmeddis@0
|
920 CNcurrentInput(:,t)/CN_cap+(CN_Gk/CN_cap).*(CN_Ek-CN_E))*dt;
|
rmeddis@0
|
921 dGk=-CN_Gk*dt./tauGk + CN_b*s;
|
rmeddis@0
|
922 dTh=-(CN_Th-CN_Th0)*dt/CN_tauTh + CN_c*s;
|
rmeddis@0
|
923 CN_E=CN_E+dE;
|
rmeddis@0
|
924 CN_Gk=CN_Gk+dGk;
|
rmeddis@0
|
925 CN_Th=CN_Th+dTh;
|
rmeddis@0
|
926 CNmembranePotential(:,t)=CN_E+s.*(CN_Eb-CN_E)+CN_Er;
|
rmeddis@0
|
927 end
|
rmeddis@0
|
928 else
|
rmeddis@0
|
929 % static threshold (faster)
|
rmeddis@0
|
930 for t=1:reducedSegmentLength
|
rmeddis@0
|
931 CNtimeSinceLastSpike=CNtimeSinceLastSpike-dt;
|
rmeddis@0
|
932 s=CN_E>CN_Th0 & CNtimeSinceLastSpike<0 ; % =1 if both conditions met
|
rmeddis@0
|
933 CNtimeSinceLastSpike(s)=0.0005; % 0.5 ms for sodium spike
|
rmeddis@0
|
934 dE = (-CN_E/CN_tauM + ...
|
rmeddis@0
|
935 CNcurrentInput(:,t)/CN_cap+(CN_Gk/CN_cap).*(CN_Ek-CN_E))*dt;
|
rmeddis@0
|
936 dGk=-CN_Gk*dt./tauGk +CN_b*s;
|
rmeddis@0
|
937 CN_E=CN_E+dE;
|
rmeddis@0
|
938 CN_Gk=CN_Gk+dGk;
|
rmeddis@0
|
939 % add spike to CN_E and add resting potential (-60 mV)
|
rmeddis@0
|
940 CNmembranePotential(:,t)=CN_E+s.*(CN_Eb-CN_E)+CN_Er;
|
rmeddis@0
|
941 end
|
rmeddis@0
|
942 end
|
rmeddis@0
|
943
|
rmeddis@0
|
944 % extract spikes. A spike is a substantial upswing in voltage
|
rmeddis@0
|
945 CN_spikes=CNmembranePotential> -0.01;
|
rmeddis@0
|
946
|
rmeddis@0
|
947 % now remove any spike that is immediately followed by a spike
|
rmeddis@0
|
948 % NB 'find' works on columns (whence the transposing)
|
rmeddis@0
|
949 CN_spikes=CN_spikes';
|
rmeddis@0
|
950 idx=find(CN_spikes);
|
rmeddis@0
|
951 idx=idx(1:end-1);
|
rmeddis@0
|
952 CN_spikes(idx+1)=0;
|
rmeddis@0
|
953 CN_spikes=CN_spikes';
|
rmeddis@0
|
954
|
rmeddis@0
|
955 % segment debugging
|
rmeddis@0
|
956 % plotInstructions.figureNo=98;
|
rmeddis@0
|
957 % plotInstructions.displaydt=ANdt;
|
rmeddis@0
|
958 % plotInstructions.numPlots=1;
|
rmeddis@0
|
959 % plotInstructions.subPlotNo=1;
|
rmeddis@0
|
960 % UTIL_plotMatrix(CN_spikes, plotInstructions);
|
rmeddis@0
|
961
|
rmeddis@0
|
962 % and save it
|
rmeddis@0
|
963 CNoutput(:, reducedSegmentPTR:shorterSegmentEndPTR)=...
|
rmeddis@0
|
964 CN_spikes;
|
rmeddis@0
|
965
|
rmeddis@0
|
966
|
rmeddis@0
|
967 %% IC ----------------------------------------------
|
rmeddis@0
|
968 % MacGregor or some other second order neurons
|
rmeddis@0
|
969
|
rmeddis@0
|
970 % combine CN neurons in same channel, i.e. same BF & same tauCa
|
rmeddis@0
|
971 % to generate inputs to single IC unit
|
rmeddis@0
|
972 channelNo=0;
|
rmeddis@0
|
973 for idx=1:nCNneuronsPerChannel:nCNneurons-nCNneuronsPerChannel+1;
|
rmeddis@0
|
974 channelNo=channelNo+1;
|
rmeddis@0
|
975 CN_PSTH(channelNo,:)=...
|
rmeddis@0
|
976 sum(CN_spikes(idx:idx+nCNneuronsPerChannel-1,:));
|
rmeddis@0
|
977 end
|
rmeddis@0
|
978
|
rmeddis@0
|
979 [alphaRows alphaCols]=size(ICtrailingAlphas);
|
rmeddis@0
|
980 for ICneuronNo=1:nICcells
|
rmeddis@0
|
981 ICcurrentTemp(ICneuronNo,:)= ...
|
rmeddis@0
|
982 conv(CN_PSTH(ICneuronNo,:), IC_CNalphaFunction);
|
rmeddis@0
|
983 end
|
rmeddis@0
|
984
|
rmeddis@0
|
985 % add the unused current from the previous convolution
|
rmeddis@0
|
986 ICcurrentTemp(:,1:alphaCols)=ICcurrentTemp(:,1:alphaCols)...
|
rmeddis@0
|
987 + ICtrailingAlphas;
|
rmeddis@0
|
988 % take what is required and keep the trailing part for next time
|
rmeddis@0
|
989 inputCurrent=ICcurrentTemp(:, 1:reducedSegmentLength);
|
rmeddis@0
|
990 ICtrailingAlphas=ICcurrentTemp(:, reducedSegmentLength+1:end);
|
rmeddis@0
|
991
|
rmeddis@0
|
992 if IC_c==0
|
rmeddis@0
|
993 % faster computation when threshold is stable (C==0)
|
rmeddis@0
|
994 for t=1:reducedSegmentLength
|
rmeddis@0
|
995 s=IC_E>IC_Th0;
|
rmeddis@0
|
996 dE = (-IC_E/IC_tauM + inputCurrent(:,t)/IC_cap +...
|
rmeddis@0
|
997 (IC_Gk/IC_cap).*(IC_Ek-IC_E))*dt;
|
rmeddis@0
|
998 dGk=-IC_Gk*dt/IC_tauGk +IC_b*s;
|
rmeddis@0
|
999 IC_E=IC_E+dE;
|
rmeddis@0
|
1000 IC_Gk=IC_Gk+dGk;
|
rmeddis@0
|
1001 ICmembranePotential(:,t)=IC_E+s.*(IC_Eb-IC_E)+IC_Er;
|
rmeddis@0
|
1002 end
|
rmeddis@0
|
1003 else
|
rmeddis@0
|
1004 % threshold is changing (IC_c>0; e.g. bushy cell)
|
rmeddis@0
|
1005 for t=1:reducedSegmentLength
|
rmeddis@0
|
1006 dE = (-IC_E/IC_tauM + ...
|
rmeddis@0
|
1007 inputCurrent(:,t)/IC_cap + (IC_Gk/IC_cap)...
|
rmeddis@0
|
1008 .*(IC_Ek-IC_E))*dt;
|
rmeddis@0
|
1009 IC_E=IC_E+dE;
|
rmeddis@0
|
1010 s=IC_E>IC_Th;
|
rmeddis@0
|
1011 ICmembranePotential(:,t)=IC_E+s.*(IC_Eb-IC_E)+IC_Er;
|
rmeddis@0
|
1012 dGk=-IC_Gk*dt/IC_tauGk +IC_b*s;
|
rmeddis@0
|
1013 IC_Gk=IC_Gk+dGk;
|
rmeddis@0
|
1014
|
rmeddis@0
|
1015 % After a spike, the threshold is raised
|
rmeddis@0
|
1016 % otherwise it settles to its baseline
|
rmeddis@0
|
1017 dTh=-(IC_Th-Th0)*dt/IC_tauTh +s*IC_c;
|
rmeddis@0
|
1018 IC_Th=IC_Th+dTh;
|
rmeddis@0
|
1019 end
|
rmeddis@0
|
1020 end
|
rmeddis@0
|
1021
|
rmeddis@0
|
1022 ICspikes=ICmembranePotential> -0.01;
|
rmeddis@0
|
1023 % now remove any spike that is immediately followed by a spike
|
rmeddis@0
|
1024 % NB 'find' works on columns (whence the transposing)
|
rmeddis@0
|
1025 ICspikes=ICspikes';
|
rmeddis@0
|
1026 idx=find(ICspikes);
|
rmeddis@0
|
1027 idx=idx(1:end-1);
|
rmeddis@0
|
1028 ICspikes(idx+1)=0;
|
rmeddis@0
|
1029 ICspikes=ICspikes';
|
rmeddis@0
|
1030
|
rmeddis@0
|
1031 nCellsPerTau= nICcells/nANfiberTypes;
|
rmeddis@0
|
1032 firstCell=1;
|
rmeddis@0
|
1033 lastCell=nCellsPerTau;
|
rmeddis@0
|
1034 for tauCount=1:nANfiberTypes
|
rmeddis@0
|
1035 % separate rates according to fiber types
|
rmeddis@0
|
1036 ICfiberTypeRates(tauCount, ...
|
rmeddis@0
|
1037 reducedSegmentPTR:shorterSegmentEndPTR)=...
|
rmeddis@0
|
1038 sum(ICspikes(firstCell:lastCell, :))...
|
rmeddis@0
|
1039 /(nCellsPerTau*ANdt);
|
rmeddis@0
|
1040 firstCell=firstCell+nCellsPerTau;
|
rmeddis@0
|
1041 lastCell=lastCell+nCellsPerTau;
|
rmeddis@0
|
1042 end
|
rmeddis@0
|
1043 ICoutput(:, reducedSegmentPTR:shorterSegmentEndPTR)=ICspikes;
|
rmeddis@0
|
1044
|
rmeddis@0
|
1045 if nBFs==1 % single channel
|
rmeddis@0
|
1046 x= repmat(ICmembranePotential(1,:), ANspeedUpFactor,1);
|
rmeddis@0
|
1047 x= reshape(x,1,segmentLength);
|
rmeddis@0
|
1048 if nANfiberTypes>1 % save HSR and LSR
|
rmeddis@0
|
1049 y= repmat(ICmembranePotential(end,:), ANspeedUpFactor,1);
|
rmeddis@0
|
1050 y= reshape(y,1,segmentLength);
|
rmeddis@0
|
1051 x=[x; y];
|
rmeddis@0
|
1052 end
|
rmeddis@0
|
1053 ICmembraneOutput(:, segmentStartPTR:segmentEndPTR)= x;
|
rmeddis@0
|
1054 end
|
rmeddis@0
|
1055
|
rmeddis@0
|
1056 % estimate efferent effects.
|
rmeddis@0
|
1057 % ARis based on LSR units. LSR channels are 1:nBF
|
rmeddis@0
|
1058 if nANfiberTypes>1 % AR is multi-channel only
|
rmeddis@0
|
1059 ARAttSeg=sum(ICspikes(1:nBFs,:),1)/ANdt;
|
rmeddis@0
|
1060 [ARAttSeg, ARboundary] = ...
|
rmeddis@0
|
1061 filter(ARfilt_b, ARfilt_a, ARAttSeg, ARboundary);
|
rmeddis@0
|
1062 ARAttSeg=ARAttSeg-ARrateThreshold;
|
rmeddis@0
|
1063 ARAttSeg(ARAttSeg<0)=0; % prevent negative strengths
|
rmeddis@0
|
1064 % scale up to dt from ANdt
|
rmeddis@0
|
1065 x= repmat(ARAttSeg, ANspeedUpFactor,1);
|
rmeddis@0
|
1066 x=reshape(x,1,segmentLength);
|
rmeddis@0
|
1067 ARattenuation(segmentStartPTR:segmentEndPTR)=...
|
rmeddis@0
|
1068 (1-ARrateToAttenuationFactor* x);
|
rmeddis@0
|
1069 ARattenuation(ARattenuation<0)=0.001;
|
rmeddis@0
|
1070 else
|
rmeddis@0
|
1071 % single channel model; disable AR
|
rmeddis@0
|
1072 ARattenuation(segmentStartPTR:segmentEndPTR)=...
|
rmeddis@0
|
1073 ones(1,segmentLength);
|
rmeddis@0
|
1074 end
|
rmeddis@0
|
1075
|
rmeddis@0
|
1076 % MOC attenuation using HSR response only
|
rmeddis@0
|
1077 % Separate MOC effect for each BF
|
rmeddis@0
|
1078 HSRbegins=nBFs*(nANfiberTypes-1)+1;
|
rmeddis@0
|
1079 rates=ICspikes(HSRbegins:end,:)/ANdt;
|
rmeddis@0
|
1080 for idx=1:nBFs
|
rmeddis@0
|
1081 [smoothedRates, MOCboundary{idx}] = ...
|
rmeddis@0
|
1082 filter(MOCfilt_b, MOCfilt_a, rates(idx,:), ...
|
rmeddis@0
|
1083 MOCboundary{idx});
|
rmeddis@0
|
1084 MOCattSegment(idx,:)=smoothedRates;
|
rmeddis@0
|
1085 % expand timescale back to model dt from ANdt
|
rmeddis@0
|
1086 x= repmat(MOCattSegment(idx,:), ANspeedUpFactor,1);
|
rmeddis@0
|
1087 x= reshape(x,1,segmentLength);
|
rmeddis@0
|
1088 MOCattenuation(idx,segmentStartPTR:segmentEndPTR)= ...
|
rmeddis@0
|
1089 (1- MOCrateToAttenuationFactor* x);
|
rmeddis@0
|
1090 end
|
rmeddis@0
|
1091 MOCattenuation(MOCattenuation<0)=0.04;
|
rmeddis@0
|
1092 % segment debugging
|
rmeddis@0
|
1093 % plotInstructions.figureNo=98;
|
rmeddis@0
|
1094 % plotInstructions.displaydt=ANdt;
|
rmeddis@0
|
1095 % plotInstructions.numPlots=1;
|
rmeddis@0
|
1096 % plotInstructions.subPlotNo=1;
|
rmeddis@0
|
1097 % UTIL_plotMatrix(ICspikes, plotInstructions);
|
rmeddis@0
|
1098
|
rmeddis@0
|
1099 end % AN_spikesOrProbability
|
rmeddis@0
|
1100 segmentStartPTR=segmentStartPTR+segmentLength;
|
rmeddis@0
|
1101 reducedSegmentPTR=reducedSegmentPTR+reducedSegmentLength;
|
rmeddis@0
|
1102
|
rmeddis@0
|
1103
|
rmeddis@0
|
1104 end % segment
|
rmeddis@0
|
1105
|
rmeddis@9
|
1106 path(restorePath)
|