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