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