|
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)
|