To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at git://github.com/rmeddis/MAP.git .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Revision:

root / MAP / MAP1_14.m @ 30:1a502830d462

History | View | Annotate | Download (44.6 KB)

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