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