Revision 38:c2204b18f4a2 MAP
| MAP/MAP1_14.m | ||
|---|---|---|
| 23 | 23 |
restorePath=path; |
| 24 | 24 |
addpath (['..' filesep 'parameterStore']) |
| 25 | 25 |
|
| 26 |
% clear global -regexp OMEParams DRNLParams IHC_cilia_RPParams IHCpreSynapseParams |
|
| 27 |
% clear global -regexp AN_IHCsynapseParams MacGregorParams MacGregorMultiParams |
|
| 28 |
% clear global -regexp dt ANdt savedBFlist saveAN_spikesOrProbability saveMAPparamsName... |
|
| 29 |
% savedInputSignal OMEextEarPressure TMoutput OMEoutput ARattenuation ... |
|
| 30 |
% DRNLoutput IHC_cilia_output IHCrestingCiliaCond IHCrestingV... |
|
| 31 |
% IHCoutput ANprobRateOutput ANoutput savePavailable ANtauCas ... |
|
| 32 |
% CNtauGk CNoutput ICoutput ICmembraneOutput ICfiberTypeRates ... |
|
| 33 |
% MOCattenuation |
|
| 34 |
|
|
| 35 | 26 |
global OMEParams DRNLParams IHC_cilia_RPParams IHCpreSynapseParams |
| 36 | 27 |
global AN_IHCsynapseParams MacGregorParams MacGregorMultiParams |
| 37 | 28 |
|
| 38 | 29 |
% All of the results of this function are stored as global |
| 39 |
global dt ANdt savedBFlist saveAN_spikesOrProbability saveMAPparamsName... |
|
| 40 |
savedInputSignal OMEextEarPressure TMoutput OMEoutput ARattenuation ... |
|
| 41 |
DRNLoutput IHC_cilia_output IHCrestingCiliaCond IHCrestingV... |
|
| 42 |
IHCoutput ANprobRateOutput ANoutput savePavailable ANtauCas ... |
|
| 43 |
CNtauGk CNoutput ICoutput ICmembraneOutput ICfiberTypeRates ... |
|
| 44 |
MOCattenuation |
|
| 30 |
global savedParamChanges savedBFlist saveAN_spikesOrProbability ... |
|
| 31 |
saveMAPparamsName savedInputSignal dt dtSpikes ... |
|
| 32 |
OMEextEarPressure TMoutput OMEoutput DRNLoutput... |
|
| 33 |
IHC_cilia_output IHCrestingCiliaCond IHCrestingV... |
|
| 34 |
IHCoutput ANprobRateOutput ANoutput savePavailable saveNavailable ... |
|
| 35 |
ANtauCas CNtauGk CNoutput ICoutput ICmembraneOutput ICfiberTypeRates... |
|
| 36 |
MOCattenuation ARattenuation |
|
| 45 | 37 |
|
| 46 | 38 |
|
| 47 | 39 |
% Normally only ICoutput(logical spike matrix) or ANprobRateOutput will be |
| 48 | 40 |
% needed by the user; so the following will suffice |
| 49 |
% global ANdt ICoutput ANprobRateOutput
|
|
| 41 |
% global dtSpikes ICoutput ANprobRateOutput
|
|
| 50 | 42 |
|
| 51 | 43 |
% Note that sampleRate has not changed from the original function call and |
| 52 | 44 |
% ANprobRateOutput is sampled at this rate |
| 53 | 45 |
% However ANoutput, CNoutput and IC output are stored as logical |
| 54 |
% 'spike' matrices using a lower sample rate (see ANdt).
|
|
| 46 |
% 'spike' matrices using a lower sample rate (see dtSpikes).
|
|
| 55 | 47 |
|
| 56 | 48 |
% When AN_spikesOrProbability is set to probability, |
| 57 | 49 |
% no spike matrices are computed. |
| ... | ... | |
| 60 | 52 |
|
| 61 | 53 |
% Efferent control variables are ARattenuation and MOCattenuation |
| 62 | 54 |
% These are scalars between 1 (no attenuation) and 0. |
| 63 |
% They are represented with dt=1/sampleRate (not ANdt)
|
|
| 55 |
% They are represented with dt=1/sampleRate (not dtSpikes)
|
|
| 64 | 56 |
% They are computed using either AN probability rate output |
| 65 | 57 |
% or IC (spikes) output as approrpriate. |
| 66 | 58 |
% AR is computed using across channel activity |
| ... | ... | |
| 85 | 77 |
savedBFlist=BFlist; |
| 86 | 78 |
saveAN_spikesOrProbability=AN_spikesOrProbability; |
| 87 | 79 |
saveMAPparamsName=MAPparamsName; |
| 80 |
savedParamChanges=paramChanges; |
|
| 88 | 81 |
|
| 89 | 82 |
dt=1/sampleRate; |
| 90 | 83 |
duration=length(inputSignal)/sampleRate; |
| ... | ... | |
| 94 | 87 |
segmentTime=dt*(1:segmentLength); % used in debugging plots |
| 95 | 88 |
|
| 96 | 89 |
% all spiking activity is computed using longer epochs |
| 97 |
ANspeedUpFactor=AN_IHCsynapseParams.ANspeedUpFactor; % e.g.5 times |
|
| 90 |
ANspeedUpFactor=ceil(sampleRate/AN_IHCsynapseParams.spikesTargetSampleRate); |
|
| 91 |
% ANspeedUpFactor=AN_IHCsynapseParams.ANspeedUpFactor; % e.g.5 times |
|
| 98 | 92 |
|
| 99 | 93 |
% inputSignal must be row vector |
| 100 | 94 |
[r c]=size(inputSignal); |
| ... | ... | |
| 115 | 109 |
inputSignal=[inputSignal pad]; |
| 116 | 110 |
[ignore signalLength]=size(inputSignal); |
| 117 | 111 |
|
| 118 |
% AN (spikes) is computed at a lower sample rate when spikes required
|
|
| 119 |
% so it has a reduced segment length (see 'ANspeeUpFactor' above)
|
|
| 112 |
% spiking activity is computed at longer sampling intervals (dtSpikes)
|
|
| 113 |
% so it has a smaller number of epochs per segment(see 'ANspeeUpFactor' above)
|
|
| 120 | 114 |
% AN CN and IC all use this sample interval |
| 121 |
ANdt=dt*ANspeedUpFactor;
|
|
| 115 |
dtSpikes=dt*ANspeedUpFactor;
|
|
| 122 | 116 |
reducedSegmentLength=round(segmentLength/ANspeedUpFactor); |
| 123 | 117 |
reducedSignalLength= round(signalLength/ANspeedUpFactor); |
| 124 | 118 |
|
| ... | ... | |
| 163 | 157 |
OME_TMdisplacementBndry=[]; |
| 164 | 158 |
|
| 165 | 159 |
% OME high pass (simulates poor low frequency stapes response) |
| 166 |
OMEhighPassHighCutOff=OMEParams.OMEstapesLPcutoff;
|
|
| 160 |
OMEhighPassHighCutOff=OMEParams.OMEstapesHPcutoff;
|
|
| 167 | 161 |
Nyquist=sampleRate/2; |
| 168 | 162 |
[stapesDisp_b,stapesDisp_a] = butter(1, OMEhighPassHighCutOff/Nyquist, 'high'); |
| 169 | 163 |
% figure(10), freqz(stapesDisp_b, stapesDisp_a) |
| ... | ... | |
| 236 | 230 |
% DRNLb=DRNLParams.b; |
| 237 | 231 |
DRNLc=DRNLParams.c; |
| 238 | 232 |
linGAIN=DRNLParams.g; |
| 239 |
CtBM=10e-9*10^(DRNLParams.CtBMdB/20);
|
|
| 240 |
CtS=CtBM/DRNLa;
|
|
| 233 |
ctBM=10e-9*10^(DRNLParams.ctBMdB/20);
|
|
| 234 |
CtS=ctBM/DRNLa;
|
|
| 241 | 235 |
% |
| 242 | 236 |
% gammatone filter coefficients for linear pathway |
| 243 | 237 |
bw=DRNLParams.linBWs'; |
| ... | ... | |
| 299 | 293 |
b0=1+ a1; |
| 300 | 294 |
% high pass (i.e. low pass reversed) |
| 301 | 295 |
IHCciliaFilter_b=[a0 a1]; IHCciliaFilter_a=b0; |
| 296 |
% i.e. b= [1 dt/tc-1] and a= dt/IHC_cilia_RPParams.tc |
|
| 302 | 297 |
% figure(9), freqz(IHCciliaFilter_b, IHCciliaFilter_a) |
| 303 | 298 |
|
| 304 | 299 |
IHCciliaBndry=cell(nBFs,1); |
| ... | ... | |
| 405 | 400 |
% special variables for monitoring synaptic cleft (specialists only) |
| 406 | 401 |
savePavailableSeg=zeros(nANchannels,segmentLength); |
| 407 | 402 |
savePavailable=zeros(nANchannels,signalLength); |
| 403 |
% only one stream of available transmitter will be saved |
|
| 404 |
saveNavailableSeg=zeros(1,reducedSegmentLength); |
|
| 405 |
saveNavailable=zeros(1,reducedSignalLength); |
|
| 408 | 406 |
|
| 409 | 407 |
% spikes % ! ! ! ! ! ! ! ! |
| 410 |
lengthAbsRefractory= round(AN_refractory_period/ANdt);
|
|
| 408 |
lengthAbsRefractory= round(AN_refractory_period/dtSpikes);
|
|
| 411 | 409 |
|
| 412 |
AN_ydt= repmat(AN_IHCsynapseParams.y*ANdt, nANfibers,1);
|
|
| 413 |
AN_ldt= repmat(AN_IHCsynapseParams.l*ANdt, nANfibers,1);
|
|
| 414 |
AN_xdt= repmat(AN_IHCsynapseParams.x*ANdt, nANfibers,1);
|
|
| 415 |
AN_rdt= repmat(AN_IHCsynapseParams.r*ANdt, nANfibers,1);
|
|
| 410 |
AN_ydt= repmat(AN_IHCsynapseParams.y*dtSpikes, nANfibers,1);
|
|
| 411 |
AN_ldt= repmat(AN_IHCsynapseParams.l*dtSpikes, nANfibers,1);
|
|
| 412 |
AN_xdt= repmat(AN_IHCsynapseParams.x*dtSpikes, nANfibers,1);
|
|
| 413 |
AN_rdt= repmat(AN_IHCsynapseParams.r*dtSpikes, nANfibers,1);
|
|
| 416 | 414 |
AN_rdt_plus_ldt= AN_rdt + AN_ldt; |
| 417 | 415 |
AN_M= round(AN_IHCsynapseParams.M); |
| 418 | 416 |
|
| ... | ... | |
| 480 | 478 |
CNdendriteLPfreq= MacGregorMultiParams.dendriteLPfreq; |
| 481 | 479 |
CNcurrentPerSpike=MacGregorMultiParams.currentPerSpike; |
| 482 | 480 |
CNspikeToCurrentTau=1/(2*pi*CNdendriteLPfreq); |
| 483 |
t=ANdt:ANdt:5*CNspikeToCurrentTau;
|
|
| 481 |
t=dtSpikes:dtSpikes:5*CNspikeToCurrentTau;
|
|
| 484 | 482 |
CNalphaFunction= (1 / ... |
| 485 | 483 |
CNspikeToCurrentTau)*t.*exp(-t /CNspikeToCurrentTau); |
| 486 | 484 |
CNalphaFunction=CNalphaFunction*CNcurrentPerSpike; |
| 487 | 485 |
|
| 488 |
% figure(98), plot(t,CNalphaFunction) |
|
| 486 |
% figure(98), plot(t,CNalphaFunction), xlim([0 .020]), xlabel('time (s)'), ylabel('I')
|
|
| 489 | 487 |
% working memory for implementing convolution |
| 490 | 488 |
|
| 491 | 489 |
CNcurrentTemp=... |
| ... | ... | |
| 520 | 518 |
CN_PSTH=zeros(nICcells ,reducedSegmentLength); |
| 521 | 519 |
|
| 522 | 520 |
% ICspikeWidth=0.00015; % this may need revisiting |
| 523 |
% epochsPerSpike=round(ICspikeWidth/ANdt);
|
|
| 521 |
% epochsPerSpike=round(ICspikeWidth/dtSpikes);
|
|
| 524 | 522 |
% if epochsPerSpike<1 |
| 525 | 523 |
% error(['MacGregorMulti: sample rate too low to support ' ... |
| 526 | 524 |
% num2str(ICspikeWidth*1e6) ' microsec spikes']); |
| ... | ... | |
| 546 | 544 |
ICdendriteLPfreq= MacGregorParams.dendriteLPfreq; |
| 547 | 545 |
ICcurrentPerSpike=MacGregorParams.currentPerSpike; |
| 548 | 546 |
ICspikeToCurrentTau=1/(2*pi*ICdendriteLPfreq); |
| 549 |
t=ANdt:ANdt:3*ICspikeToCurrentTau;
|
|
| 547 |
t=dtSpikes:dtSpikes:3*ICspikeToCurrentTau;
|
|
| 550 | 548 |
IC_CNalphaFunction= (ICcurrentPerSpike / ... |
| 551 | 549 |
ICspikeToCurrentTau)*t.*exp(-t / ICspikeToCurrentTau); |
| 552 | 550 |
% figure(98), plot(t,IC_CNalphaFunction) |
| ... | ... | |
| 661 | 659 |
nonlinOutput, GTnonlinBdry1{BFno,order});
|
| 662 | 660 |
end |
| 663 | 661 |
|
| 662 |
|
|
| 664 | 663 |
% Nick's compression algorithm |
| 665 |
abs_x = abs(nonlinOutput); |
|
| 666 |
y(abs_x<CtS) = DRNLa * nonlinOutput(abs_x<CtS); |
|
| 667 |
y(abs_x>=CtS) = sign(nonlinOutput(abs_x>=CtS)) * DRNLa * CtS .* ... |
|
| 668 |
exp( DRNLc * log( abs_x(abs_x>=CtS)/CtS ) ); |
|
| 669 |
nonlinOutput=y; |
|
| 664 |
abs_x= abs(nonlinOutput); |
|
| 665 |
signs= sign(nonlinOutput); |
|
| 666 |
belowThreshold= abs_x<CtS; |
|
| 667 |
nonlinOutput(belowThreshold)= DRNLa *nonlinOutput(belowThreshold); |
|
| 668 |
aboveThreshold=~belowThreshold; |
|
| 669 |
nonlinOutput(aboveThreshold)= signs(aboveThreshold) *ctBM .* ... |
|
| 670 |
exp(DRNLc *log( DRNLa*abs_x(aboveThreshold)/ctBM )); |
|
| 671 |
|
|
| 670 | 672 |
|
| 671 | 673 |
% % original broken stick instantaneous compression |
| 672 | 674 |
% holdY=nonlinOutput; |
| ... | ... | |
| 688 | 690 |
% end |
| 689 | 691 |
% nonlinOutput=y; |
| 690 | 692 |
|
| 691 |
% % Boltzmann compression function |
|
| 692 |
% y=(nonlinOutput * DRNLa*100000); |
|
| 693 |
% holdY=y; |
|
| 694 |
% y=abs(y); |
|
| 695 |
% s=10; u=0.0; |
|
| 696 |
% x=1./(1+exp(-(y-u)/s))-0.5; |
|
| 697 |
% nonlinOutput=sign(nonlinOutput).*x/10000; |
|
| 698 | 693 |
|
| 694 |
% if segmentStartPTR==10*segmentLength+1 |
|
| 695 |
% figure(90) |
|
| 696 |
% plot(holdY,'b'), hold on |
|
| 697 |
% plot(nonlinOutput, 'r'), hold off |
|
| 698 |
% ylim([-1e-5 1e-5]) |
|
| 699 |
% pause(1) |
|
| 700 |
% end |
|
| 699 | 701 |
|
| 700 |
% if segmentStartPTR==10*segmentLength+1 |
|
| 701 |
% figure(90) |
|
| 702 |
% plot(holdY,'b'), hold on |
|
| 703 |
% plot(nonlinOutput, 'r'), hold off |
|
| 704 |
% ylim([-1e-5 1e-5]) |
|
| 705 |
% pause(1) |
|
| 706 |
% end |
|
| 707 |
|
|
| 708 |
% second filter removes distortion products |
|
| 702 |
% second filter removes distortion products |
|
| 709 | 703 |
for order = 1 : GTnonlinOrder |
| 710 | 704 |
[ nonlinOutput GTnonlinBdry2{BFno,order}] = ...
|
| 711 | 705 |
filter(GTnonlin_b(BFno,:), GTnonlin_a(BFno,:), ... |
| ... | ... | |
| 839 | 833 |
% the probability of a spike's occurring in the preceding |
| 840 | 834 |
% refractory window: t= (tnow-refractory period) :dt: tnow |
| 841 | 835 |
% pFired= 1 - II(1-p(t)), |
| 842 |
% we need a running account of cumProb=II(1-p(t)) |
|
| 836 |
% we need a running account of cumProb=II(1-p(t)) in order |
|
| 837 |
% not to have to recompute this for each value of t |
|
| 843 | 838 |
% cumProb(t)= cumProb(t-1)*(1-p(t))/(1-p(t-refracPeriod)) |
| 844 | 839 |
% cumProb(0)=0 |
| 845 | 840 |
% pFired(t)= 1-cumProb(t) |
| ... | ... | |
| 869 | 864 |
% figure(88), plot(cumANnotFireProb'), title('cumNotFire')
|
| 870 | 865 |
% figure(89), plot(ANprobRateOutput'), title('ANprobRateOutput')
|
| 871 | 866 |
|
| 872 |
%% Estimate efferent effect: 0 < ARattenuation > 1 |
|
| 873 |
% acoustic reflex |
|
| 867 |
%% Estimate acoustic reflex efferent effect: 0 < ARattenuation > 1 |
|
| 874 | 868 |
[r c]=size(ANrate); |
| 875 | 869 |
if r>nBFs % Only if LSR fibers are computed |
| 876 | 870 |
ARAttSeg=mean(ANrate(1:nBFs,:),1); %LSR channels are 1:nBF |
| ... | ... | |
| 893 | 887 |
ones(size(rates))* -rateToAttenuationFactorProb; |
| 894 | 888 |
else |
| 895 | 889 |
|
| 896 |
% Nick's new code |
|
| 897 |
% for idx=1:nBFs |
|
| 898 |
% [smoothedRates, MOCprobBoundary{idx}] = ...
|
|
| 899 |
% filter(MOCfilt_b, MOCfilt_a, rates(idx,:), ... |
|
| 900 |
% MOCprobBoundary{idx});
|
|
| 901 |
% % smoothedRates=smoothedRates-MOCrateThresholdProb; |
|
| 902 |
% % smoothedRates(smoothedRates<0)=0; |
|
| 903 |
% % x = (1- smoothedRates* rateToAttenuationFactorProb); %ORIGINAL |
|
| 904 |
% |
|
| 905 |
% %NEW !!! |
|
| 906 |
% x = -20*log10( max(smoothedRates/MOCrateThresholdProb,1) )*rateToAttenuationFactorProb; %dB attenuation |
|
| 907 |
% x = 10.^(x/20); |
|
| 908 |
% x = max(x,10^(-35/20)); |
|
| 909 |
% % %ALSO - filter at the end - this will stop rapid attack |
|
| 910 |
% % %and slow decay |
|
| 911 |
% % [x, MOCprobBoundary{idx}] = ...
|
|
| 912 |
% % filter(MOCfilt_b, MOCfilt_a, x, ... |
|
| 913 |
% % MOCprobBoundary{idx});
|
|
| 914 |
% |
|
| 915 |
% |
|
| 916 |
% MOCattenuation(idx,segmentStartPTR:segmentEndPTR)= ... |
|
| 917 |
% x; |
|
| 918 |
% end |
|
| 919 |
|
|
| 920 |
|
|
| 921 | 890 |
for idx=1:nBFs |
| 922 | 891 |
[smoothedRates, MOCprobBoundary{idx}] = ...
|
| 923 | 892 |
filter(MOCfiltProb_b, MOCfiltProb_a, rates(idx,:), ... |
| ... | ... | |
| 940 | 909 |
for t = ANspeedUpFactor:ANspeedUpFactor:segmentLength; |
| 941 | 910 |
ANtimeCount=ANtimeCount+1; |
| 942 | 911 |
% convert release rate to probabilities |
| 943 |
releaseProb=vesicleReleaseRate(:,t)*ANdt;
|
|
| 912 |
releaseProb=vesicleReleaseRate(:,t)*dtSpikes;
|
|
| 944 | 913 |
% releaseProb is the release probability per channel |
| 945 | 914 |
% but each channel has many synapses |
| 946 | 915 |
releaseProb=repmat(releaseProb',nFibersPerChannel,1); |
| ... | ... | |
| 968 | 937 |
|
| 969 | 938 |
AN_available = AN_available + replenish - ejected ... |
| 970 | 939 |
+ reprocessed; |
| 940 |
saveNavailableSeg(:,ANtimeCount)=AN_available(end,:); % only last channel |
|
| 941 |
|
|
| 971 | 942 |
AN_cleft = AN_cleft + ejected - reuptakeandlost; |
| 972 | 943 |
AN_reprocess = AN_reprocess + reuptake - reprocessed; |
| 973 | 944 |
|
| ... | ... | |
| 1003 | 974 |
|
| 1004 | 975 |
% segment debugging |
| 1005 | 976 |
% plotInstructions.figureNo=98; |
| 1006 |
% plotInstructions.displaydt=ANdt;
|
|
| 977 |
% plotInstructions.displaydt=dtSpikes;
|
|
| 1007 | 978 |
% plotInstructions.numPlots=1; |
| 1008 | 979 |
% plotInstructions.subPlotNo=1; |
| 1009 | 980 |
% UTIL_plotMatrix(ANspikes, plotInstructions); |
| 1010 | 981 |
|
| 1011 | 982 |
% and save it. NB, AN is now on 'speedUp' time |
| 1012 | 983 |
ANoutput(:, reducedSegmentPTR: shorterSegmentEndPTR)=ANspikes; |
| 984 |
% monitor synapse contents (only sometimes used) |
|
| 985 |
saveNavailable(reducedSegmentPTR:reducedSegmentPTR+reducedSegmentLength-1)=... |
|
| 986 |
saveNavailableSeg; |
|
| 1013 | 987 |
|
| 1014 | 988 |
|
| 1015 | 989 |
%% CN Macgregor first neucleus ------------------------------- |
| 1016 |
% input is from AN so ANdt is used throughout
|
|
| 990 |
% input is from AN so dtSpikes is used throughout
|
|
| 1017 | 991 |
% Each CNneuron has a unique set of input fibers selected |
| 1018 | 992 |
% at random from the available AN fibers (CNinputfiberLists) |
| 1019 | 993 |
|
| ... | ... | |
| 1024 | 998 |
for idx=1:nCNneuronsPerChannel |
| 1025 | 999 |
% determine candidate fibers for this unit |
| 1026 | 1000 |
fibersUsed=CNinputfiberLists(synapseNo,:); |
| 1027 |
% ANpsth has a bin width of ANdt
|
|
| 1001 |
% ANpsth has a bin width of dtSpikes
|
|
| 1028 | 1002 |
% (just a simple sum across fibers) |
| 1029 | 1003 |
AN_PSTH(synapseNo,:) = ... |
| 1030 | 1004 |
sum(ANspikes(fibersUsed,:), 1); |
| ... | ... | |
| 1056 | 1030 |
if CN_c>0 |
| 1057 | 1031 |
% variable threshold condition (slow) |
| 1058 | 1032 |
for t=1:reducedSegmentLength |
| 1059 |
CNtimeSinceLastSpike=CNtimeSinceLastSpike-ANdt;
|
|
| 1033 |
CNtimeSinceLastSpike=CNtimeSinceLastSpike-dtSpikes;
|
|
| 1060 | 1034 |
s=CN_E>CN_Th & CNtimeSinceLastSpike<0 ; |
| 1061 | 1035 |
CNtimeSinceLastSpike(s)=0.0005; % 0.5 ms for sodium spike |
| 1062 | 1036 |
dE =(-CN_E/CN_tauM + ... |
| 1063 | 1037 |
CNcurrentInput(:,t)/CN_cap+(... |
| 1064 |
CN_Gk/CN_cap).*(CN_Ek-CN_E))*ANdt;
|
|
| 1065 |
dGk=-CN_Gk*ANdt./tauGk + CN_b*s;
|
|
| 1066 |
dTh=-(CN_Th-CN_Th0)*ANdt/CN_tauTh + CN_c*s;
|
|
| 1038 |
CN_Gk/CN_cap).*(CN_Ek-CN_E))*dtSpikes;
|
|
| 1039 |
dGk=-CN_Gk*dtSpikes./tauGk + CN_b*s;
|
|
| 1040 |
dTh=-(CN_Th-CN_Th0)*dtSpikes/CN_tauTh + CN_c*s;
|
|
| 1067 | 1041 |
CN_E=CN_E+dE; |
| 1068 | 1042 |
CN_Gk=CN_Gk+dGk; |
| 1069 | 1043 |
CN_Th=CN_Th+dTh; |
| ... | ... | |
| 1076 | 1050 |
ss=zeros(1,reducedSegmentLength); |
| 1077 | 1051 |
for t=1:reducedSegmentLength |
| 1078 | 1052 |
% time of previous spike moves back in time |
| 1079 |
CNtimeSinceLastSpike=CNtimeSinceLastSpike-ANdt;
|
|
| 1053 |
CNtimeSinceLastSpike=CNtimeSinceLastSpike-dtSpikes;
|
|
| 1080 | 1054 |
% action potential if E>threshold |
| 1081 | 1055 |
% allow time for s to reset between events |
| 1082 | 1056 |
s=CN_E>CN_Th0 & CNtimeSinceLastSpike<0 ; |
| ... | ... | |
| 1084 | 1058 |
CNtimeSinceLastSpike(s)=0.0005; % 0.5 ms for sodium spike |
| 1085 | 1059 |
dE = (-CN_E/CN_tauM + ... |
| 1086 | 1060 |
CNcurrentInput(:,t)/CN_cap +... |
| 1087 |
(CN_Gk/CN_cap).*(CN_Ek-CN_E))*ANdt;
|
|
| 1088 |
dGk=-CN_Gk*ANdt./tauGk +CN_b*s;
|
|
| 1061 |
(CN_Gk/CN_cap).*(CN_Ek-CN_E))*dtSpikes;
|
|
| 1062 |
dGk=-CN_Gk*dtSpikes./tauGk +CN_b*s;
|
|
| 1089 | 1063 |
CN_E=CN_E+dE; |
| 1090 | 1064 |
CN_Gk=CN_Gk+dGk; |
| 1091 | 1065 |
E(t)=CN_E(1); |
| ... | ... | |
| 1116 | 1090 |
|
| 1117 | 1091 |
% segment debugging |
| 1118 | 1092 |
% plotInstructions.figureNo=98; |
| 1119 |
% plotInstructions.displaydt=ANdt;
|
|
| 1093 |
% plotInstructions.displaydt=dtSpikes;
|
|
| 1120 | 1094 |
% plotInstructions.numPlots=1; |
| 1121 | 1095 |
% plotInstructions.subPlotNo=1; |
| 1122 | 1096 |
% UTIL_plotMatrix(CN_spikes, plotInstructions); |
| ... | ... | |
| 1158 | 1132 |
for t=1:reducedSegmentLength |
| 1159 | 1133 |
s=IC_E>IC_Th0; |
| 1160 | 1134 |
dE = (-IC_E/IC_tauM + inputCurrent(:,t)/IC_cap +... |
| 1161 |
(IC_Gk/IC_cap).*(IC_Ek-IC_E))*ANdt;
|
|
| 1162 |
dGk=-IC_Gk*ANdt/IC_tauGk +IC_b*s;
|
|
| 1135 |
(IC_Gk/IC_cap).*(IC_Ek-IC_E))*dtSpikes;
|
|
| 1136 |
dGk=-IC_Gk*dtSpikes/IC_tauGk +IC_b*s;
|
|
| 1163 | 1137 |
IC_E=IC_E+dE; |
| 1164 | 1138 |
IC_Gk=IC_Gk+dGk; |
| 1165 | 1139 |
ICmembranePotential(:,t)=IC_E+s.*(IC_Eb-IC_E)+IC_Er; |
| ... | ... | |
| 1169 | 1143 |
for t=1:reducedSegmentLength |
| 1170 | 1144 |
dE = (-IC_E/IC_tauM + ... |
| 1171 | 1145 |
inputCurrent(:,t)/IC_cap + (IC_Gk/IC_cap)... |
| 1172 |
.*(IC_Ek-IC_E))*ANdt;
|
|
| 1146 |
.*(IC_Ek-IC_E))*dtSpikes;
|
|
| 1173 | 1147 |
IC_E=IC_E+dE; |
| 1174 | 1148 |
s=IC_E>IC_Th; |
| 1175 | 1149 |
ICmembranePotential(:,t)=IC_E+s.*(IC_Eb-IC_E)+IC_Er; |
| 1176 |
dGk=-IC_Gk*ANdt/IC_tauGk +IC_b*s;
|
|
| 1150 |
dGk=-IC_Gk*dtSpikes/IC_tauGk +IC_b*s;
|
|
| 1177 | 1151 |
IC_Gk=IC_Gk+dGk; |
| 1178 | 1152 |
|
| 1179 | 1153 |
% After a spike, the threshold is raised |
| 1180 | 1154 |
% otherwise it settles to its baseline |
| 1181 |
dTh=-(IC_Th-Th0)*ANdt/IC_tauTh +s*IC_c;
|
|
| 1155 |
dTh=-(IC_Th-Th0)*dtSpikes/IC_tauTh +s*IC_c;
|
|
| 1182 | 1156 |
IC_Th=IC_Th+dTh; |
| 1183 | 1157 |
end |
| 1184 | 1158 |
end |
| ... | ... | |
| 1202 | 1176 |
ICfiberTypeRates(tauCount, ... |
| 1203 | 1177 |
reducedSegmentPTR:shorterSegmentEndPTR)=... |
| 1204 | 1178 |
sum(ICspikes(firstCell:lastCell, :))... |
| 1205 |
/(nCellsPerTau*ANdt);
|
|
| 1179 |
/(nCellsPerTau*dtSpikes);
|
|
| 1206 | 1180 |
firstCell=firstCell+nCellsPerTau; |
| 1207 | 1181 |
lastCell=lastCell+nCellsPerTau; |
| 1208 | 1182 |
end |
| ... | ... | |
| 1230 | 1204 |
% figure(4),plot(ICmembraneOutput(2,:)) |
| 1231 | 1205 |
|
| 1232 | 1206 |
% estimate efferent effects. |
| 1233 |
% ARis based on LSR units. LSR channels are 1:nBF |
|
| 1207 |
% AR is based on LSR units. LSR channels are 1:nBF
|
|
| 1234 | 1208 |
if nANfiberTypes>1 % use only if model is multi-fiber |
| 1235 |
ARAttSeg=mean(ICspikes(1:nBFs,:),1)/ANdt;
|
|
| 1209 |
ARAttSeg=mean(ICspikes(1:nBFs,:),1)/dtSpikes;
|
|
| 1236 | 1210 |
[ARAttSeg, ARboundary] = ... |
| 1237 | 1211 |
filter(ARfilt_b, ARfilt_a, ARAttSeg, ARboundary); |
| 1238 |
% ARAttSeg(ARAttSeg<0)=0; % prevent negative strengths
|
|
| 1239 |
% scale up to dt from ANdt
|
|
| 1212 |
% ARAttSeg(ARAttSeg<0)=0; % prevent negative strengths |
|
| 1213 |
% scale up to dt from dtSpikes
|
|
| 1240 | 1214 |
x= repmat(ARAttSeg, ANspeedUpFactor,1); |
| 1241 | 1215 |
x= reshape(x,1,segmentLength); |
| 1242 | 1216 |
ARattenuation(segmentStartPTR:segmentEndPTR)=... |
| 1243 | 1217 |
(1-ARrateToAttenuationFactor* x); |
| 1244 | 1218 |
% max 60 dB attenuation |
| 1245 |
ARattenuation(ARattenuation<0)=0.001;
|
|
| 1219 |
ARattenuation(ARattenuation<0)=0.01; |
|
| 1246 | 1220 |
else |
| 1247 | 1221 |
% single fiber type; disable AR because no LSR fibers |
| 1248 | 1222 |
ARattenuation(segmentStartPTR:segmentEndPTR)=... |
| ... | ... | |
| 1253 | 1227 |
% separate MOC effect for each BF |
| 1254 | 1228 |
% there is only one unit per channel |
| 1255 | 1229 |
HSRbegins=nBFs*(nANfiberTypes-1)+1; |
| 1256 |
rates=ICspikes(HSRbegins:end,:)/ANdt;
|
|
| 1230 |
rates=ICspikes(HSRbegins:end,:)/dtSpikes;
|
|
| 1257 | 1231 |
% figure(4),plot(rates(1,:)) |
| 1258 | 1232 |
|
| 1259 | 1233 |
for idx=1:nBFs |
| ... | ... | |
| 1262 | 1236 |
MOCboundary{idx});
|
| 1263 | 1237 |
% spont 'rates' is zero for IC |
| 1264 | 1238 |
MOCattSegment(idx,:)=smoothedRates; |
| 1265 |
% expand timescale back to model dt from ANdt
|
|
| 1239 |
% expand timescale back to model dt from dtSpikes
|
|
| 1266 | 1240 |
x= repmat(MOCattSegment(idx,:), ANspeedUpFactor,1); |
| 1267 | 1241 |
x= reshape(x,1,segmentLength); |
| 1268 | 1242 |
MOCattenuation(idx,segmentStartPTR:segmentEndPTR)= ... |
| ... | ... | |
| 1276 | 1250 |
|
| 1277 | 1251 |
% segment debugging |
| 1278 | 1252 |
% plotInstructions.figureNo=98; |
| 1279 |
% plotInstructions.displaydt=ANdt;
|
|
| 1253 |
% plotInstructions.displaydt=dtSpikes;
|
|
| 1280 | 1254 |
% plotInstructions.numPlots=1; |
| 1281 | 1255 |
% plotInstructions.subPlotNo=1; |
| 1282 | 1256 |
% UTIL_plotMatrix(ICspikes, plotInstructions); |
| MAP/MAPrunner.m | ||
|---|---|---|
| 1 |
function MAPrunner(MAPparamsName, AN_spikesOrProbability, ... |
|
| 2 |
signalCharacteristics, paramChanges, showMapOptions) |
|
| 3 |
|
|
| 4 |
dbstop if error |
|
| 5 |
restorePath=path; |
|
| 6 |
addpath (['..' filesep 'MAP'], ['..' filesep 'wavFileStore'], ... |
|
| 7 |
['..' filesep 'utilities']) |
|
| 8 |
|
|
| 9 |
|
|
| 10 |
%% #3 pure tone, harmonic sequence or speech file input |
|
| 11 |
signalType= signalCharacteristics.type; |
|
| 12 |
sampleRate= signalCharacteristics.sampleRate; |
|
| 13 |
duration=signalCharacteristics.duration; % seconds |
|
| 14 |
rampDuration=signalCharacteristics.rampDuration; % raised cosine ramp (seconds) |
|
| 15 |
beginSilence=signalCharacteristics.beginSilence; |
|
| 16 |
endSilence=signalCharacteristics.endSilence; |
|
| 17 |
toneFrequency= signalCharacteristics.toneFrequency; % or a pure tone (Hz) |
|
| 18 |
leveldBSPL=signalCharacteristics.leveldBSPL; |
|
| 19 |
|
|
| 20 |
BFlist=-1; |
|
| 21 |
|
|
| 22 |
|
|
| 23 |
%% Generate stimuli |
|
| 24 |
|
|
| 25 |
switch signalType |
|
| 26 |
case 'tones' |
|
| 27 |
% Create pure tone stimulus |
|
| 28 |
dt=1/sampleRate; % seconds |
|
| 29 |
time=dt: dt: duration; |
|
| 30 |
inputSignal=sum(sin(2*pi*toneFrequency'*time), 1); |
|
| 31 |
amp=10^(leveldBSPL/20)*28e-6; % converts to Pascals (peak) |
|
| 32 |
inputSignal=amp*inputSignal; |
|
| 33 |
% apply ramps |
|
| 34 |
% catch rampTime error |
|
| 35 |
if rampDuration>0.5*duration, rampDuration=duration/2; end |
|
| 36 |
rampTime=dt:dt:rampDuration; |
|
| 37 |
ramp=[0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ... |
|
| 38 |
ones(1,length(time)-length(rampTime))]; |
|
| 39 |
inputSignal=inputSignal.*ramp; |
|
| 40 |
ramp=fliplr(ramp); |
|
| 41 |
inputSignal=inputSignal.*ramp; |
|
| 42 |
% add silence |
|
| 43 |
intialSilence= zeros(1,round(beginSilence/dt)); |
|
| 44 |
finalSilence= zeros(1,round(endSilence/dt)); |
|
| 45 |
inputSignal= [intialSilence inputSignal finalSilence]; |
|
| 46 |
|
|
| 47 |
case 'file' |
|
| 48 |
%% file input simple or mixed |
|
| 49 |
[inputSignal sampleRate]=wavread(fileName); |
|
| 50 |
dt=1/sampleRate; |
|
| 51 |
inputSignal=inputSignal(:,1); |
|
| 52 |
targetRMS=20e-6*10^(leveldBSPL/20); |
|
| 53 |
rms=(mean(inputSignal.^2))^0.5; |
|
| 54 |
amp=targetRMS/rms; |
|
| 55 |
inputSignal=inputSignal*amp; |
|
| 56 |
intialSilence= zeros(1,round(0.1/dt)); |
|
| 57 |
finalSilence= zeros(1,round(0.2/dt)); |
|
| 58 |
inputSignal= [intialSilence inputSignal' finalSilence]; |
|
| 59 |
end |
|
| 60 |
|
|
| 61 |
|
|
| 62 |
%% run the model |
|
| 63 |
|
|
| 64 |
MAP1_14(inputSignal, sampleRate, BFlist, ... |
|
| 65 |
MAPparamsName, AN_spikesOrProbability, paramChanges); |
|
| 66 |
|
|
| 67 |
%% the model run is now complete. Now display the results |
|
| 68 |
UTIL_showMAP(showMapOptions, paramChanges) |
|
| 69 |
|
|
| 70 |
path(restorePath) |
|
| 71 |
|
|
| MAP/filteredSACF.m | ||
|---|---|---|
| 1 |
function [P, BFlist, sacf, boundaryValue] = ... |
|
| 2 |
filteredSACF(inputSignalMatrix, method, params) |
|
| 3 |
% UTIL_filteredSACF computes within-channel, running autocorrelations (acfs) |
|
| 4 |
% and finds the sum across channels (sacf). |
|
| 5 |
% The SACF is smoothed to give the 'p function' (P). |
|
| 1 |
function [LP_SACF, BFlist, SACF, ACFboundaryValue] = ... |
|
| 2 |
filteredSACF(inputSignalMatrix, dt, BFlist, params) |
|
| 3 |
% UTIL_filteredSACF computes within-channel, running autocorrelations (ACFs) |
|
| 4 |
% and finds the running sum across channels (SACF). |
|
| 5 |
% The SACF is smoothed to give the 'p function' (LP_SACF). |
|
| 6 |
% (Balaguer-Ballestera, E. Denham, S.L. and Meddis, R. (2008)) |
|
| 7 |
% |
|
| 6 | 8 |
% |
| 7 | 9 |
% INPUT |
| 8 | 10 |
% inputSignalMatrix: a matrix (channel x time) of AN activity |
| 9 |
% method.dt: the signal sampling interval in seconds |
|
| 10 |
% method.segmentNo: |
|
| 11 |
% method.nonlinCF |
|
| 12 |
% |
|
| 11 |
% dt: the signal sampling interval in seconds |
|
| 12 |
% BFlist: channel BFs |
|
| 13 |
% |
|
| 13 | 14 |
% params: a list of parmeters to guide the computation: |
| 14 |
% filteredSACFParams.lags: an array of lags to be computed (seconds)
|
|
| 15 |
% filteredSACFParams.acfTau: time constant (sec) of the running acf calculations
|
|
| 16 |
% if acfTau>1 it is assumed that Wiegrebe'sacf method
|
|
| 15 |
% params.lags: an array of lags to be computed (seconds)
|
|
| 16 |
% params.acfTau: time constant (sec) of the running ACF
|
|
| 17 |
% if acfTau>1 it is assumed that Wiegrebe'SACF method
|
|
| 17 | 18 |
% for calculating tau is to be used (see below) |
| 18 |
% filteredSACFParams.Lambda: time constant for smoothing thsacf to make P |
|
| 19 |
% filteredSACFParams.lagsProcedure identifies a strategy for omitting some lags. |
|
| 20 |
% Options are: 'useAllLags', 'omitShortLags', or 'useBernsteinLagWeights' |
|
| 21 |
% filteredSACFParams.usePressnitzer applies lower weights longer lags |
|
| 22 |
% parafilteredSACFParamsms.plotACFs (=1) creates movie of acf matrix (optional) |
|
| 23 |
% |
|
| 19 |
% params.Lambda: smoothing factor for the SACF |
|
| 20 |
% params.lagsProcedure: strategies for omitting some lags. |
|
| 21 |
% (Options: 'useAllLags' or 'omitShortLags') |
|
| 22 |
% params.usePressnitzer applies lower weights longer lags |
|
| 23 |
% params.plotACFs (=1) creates movie of ACF matrix (optional) |
|
| 24 | 24 |
% |
| 25 | 25 |
% OUTPUT |
| 26 |
% P: P function (time x lags), a low pass filtered version of sacf. |
|
| 27 |
% method: updated version of input method (to include lags used) |
|
| 28 |
% sacf: (time x lags) |
|
| 26 |
% LP_SACF: LP_SACF function (time x lags), a low pass filtered version of SACF. |
|
| 27 |
% method: updated version of input 'method' (to include lags used) |
|
| 28 |
% SACF: (time x lags) |
|
| 29 |
% |
|
| 30 |
% Notes: |
|
| 31 |
% ACFboundaryValue refers to segmented evaluation and is currently not |
|
| 32 |
% supported. However the code may be useful later when this function |
|
| 33 |
% is incorporated into MAP1_14. |
|
| 29 | 34 |
|
| 30 | 35 |
%% |
| 31 |
boundaryValue=[]; |
|
| 36 |
global savedInputSignal |
|
| 37 |
|
|
| 38 |
ACFboundaryValue=[]; |
|
| 39 |
|
|
| 32 | 40 |
[nChannels inputLength]= size(inputSignalMatrix); |
| 33 |
% list of BFs must be repeated is many fiber types used |
|
| 34 |
BFlist=method.nonlinCF; |
|
| 35 |
nfibertypes=nChannels/length(BFlist); |
|
| 36 |
BFlist=repmat(BFlist',2,1)'; |
|
| 37 | 41 |
|
| 38 |
dt=method.dt; |
|
| 39 |
% adjust sample rate, if required |
|
| 40 |
if isfield(params,'dt') |
|
| 41 |
[inputSignalMatrix dt]=UTIL_adjustDT(params.dt, method.dt, inputSignalMatrix); |
|
| 42 |
method.dt=dt; |
|
| 43 |
end |
|
| 44 |
|
|
| 45 |
% create acf movie |
|
| 42 |
% create ACF movie |
|
| 46 | 43 |
if isfield(params, 'plotACFs') && params.plotACFs==1 |
| 47 | 44 |
plotACF=1; |
| 45 |
signalTime=dt:dt:dt*length(savedInputSignal); |
|
| 48 | 46 |
else |
| 49 | 47 |
plotACF=0; % default |
| 50 | 48 |
end |
| 49 |
params.plotACFsInterval=round(params.plotACFsInterval/dt); |
|
| 51 | 50 |
|
| 52 | 51 |
if isfield(params,'lags') |
| 53 | 52 |
lags=params.lags; |
| ... | ... | |
| 64 | 63 |
else |
| 65 | 64 |
lagsProcedure='useAllLags'; % default |
| 66 | 65 |
end |
| 67 |
% disp(['lag procedure= ''' lagsProcedure '''']) |
|
| 66 |
|
|
| 68 | 67 |
lagWeights=ones(nChannels,nLags); |
| 69 | 68 |
switch lagsProcedure |
| 70 | 69 |
case 'useAllLags' |
| 71 |
% no action required lagWeights set above |
|
| 70 |
% no action required lagWeights set above
|
|
| 72 | 71 |
case 'omitShortLags' |
| 73 | 72 |
% remove lags that are short relative to CF |
| 74 | 73 |
allLags=repmat(lags,nChannels,1); |
| ... | ... | |
| 76 | 75 |
criterionForOmittingLags=1./(params.criterionForOmittingLags*allCFs); |
| 77 | 76 |
idx= allLags < criterionForOmittingLags; % ignore these lags |
| 78 | 77 |
lagWeights(idx)=0; |
| 79 |
case 'useBernsteinLagWeights' |
|
| 80 |
lagWeights=BernsteinLags(BFlist, lags)'; |
|
| 81 | 78 |
otherwise |
| 82 |
error ('acf: params.lagProcedure not recognised')
|
|
| 79 |
error ('ACF: params.lagProcedure not recognised')
|
|
| 83 | 80 |
end |
| 84 | 81 |
|
| 85 | 82 |
|
| 86 |
% Establish matrix of lag time constants
|
|
| 83 |
% Establish matrix of lag time constants |
|
| 87 | 84 |
% these are all the same if tau<1 |
| 88 | 85 |
% if acfTau>1, it is assumed that we are using the Wiegrebe method |
| 89 | 86 |
% and a different decay factor is applied to each lag |
| ... | ... | |
| 92 | 89 |
if acfTau<1 % all taus are the same |
| 93 | 90 |
acfTaus=repmat(acfTau, 1, nLags); |
| 94 | 91 |
acfDecayFactors=ones(size(lags)).*exp(-dt/acfTau); |
| 95 |
else % use Wiegrebe method: tau= 2*lag (for example)
|
|
| 92 |
else % use Wiegrebe method: tau= 2*lag (for example) |
|
| 96 | 93 |
WiegrebeFactor=acfTau; |
| 97 | 94 |
acfTaus=WiegrebeFactor*lags; |
| 98 | 95 |
idx= acfTaus<0.0025; acfTaus(idx)=0.0025; |
| ... | ... | |
| 101 | 98 |
% make acfDecayFactors into a (channels x lags) matrix for speedy computation |
| 102 | 99 |
acfDecayFactors=repmat(acfDecayFactors,nChannels, 1); |
| 103 | 100 |
|
| 104 |
% P function lowpass filter decay (only one value needed)
|
|
| 101 |
% LP_SACF function lowpass filter decay (only one value needed)
|
|
| 105 | 102 |
pDecayFactor=exp(-dt/params.lambda); |
| 106 | 103 |
|
| 107 | 104 |
% ACF |
| ... | ... | |
| 112 | 109 |
end |
| 113 | 110 |
|
| 114 | 111 |
|
| 115 |
P=zeros(nLags,inputLength+1); % P must match segment length +1 |
|
| 116 |
sacf=zeros(nLags,inputLength); |
|
| 112 |
LP_SACF=zeros(nLags,inputLength+1); % LP_SACF must match segment length +1 |
|
| 113 |
SACF=zeros(nLags,inputLength); |
|
| 114 |
method=[]; % legacy programming |
|
| 117 | 115 |
if ~isfield(method,'segmentNumber') || method.segmentNumber==1 |
| 118 |
acf=zeros(nChannels,nLags);
|
|
| 116 |
ACF=zeros(nChannels,nLags);
|
|
| 119 | 117 |
% create a runup buffer of signal |
| 120 | 118 |
buffer= zeros(nChannels, max(lagPointers)); |
| 121 | 119 |
else |
| 122 |
% boundaryValue picks up from a previous calculation |
|
| 123 |
acf=params.boundaryValue{1};
|
|
| 124 |
P(: , 1)=params.boundaryValue{2}; % NB first value is last value of previous segment
|
|
| 125 |
buffer=params.boundaryValue{3};
|
|
| 120 |
% ACFboundaryValue picks up from a previous calculation |
|
| 121 |
ACF=params.ACFboundaryValue{1};
|
|
| 122 |
% NB first value is last value of previous segment |
|
| 123 |
LP_SACF(: , 1)=params.ACFboundaryValue{2};
|
|
| 124 |
buffer=params.ACFboundaryValue{3};
|
|
| 126 | 125 |
end |
| 127 | 126 |
inputSignalMatrix=[buffer inputSignalMatrix]; |
| 128 | 127 |
[nChannels inputLength]= size(inputSignalMatrix); |
| 129 | 128 |
|
| 130 | 129 |
timeCounter=0; biggestSACF=0; |
| 131 | 130 |
for timePointer= max(lagPointers)+1:inputLength |
| 132 |
% acf is a continuously changing channels x lags matrix
|
|
| 131 |
% ACF is a continuously changing channels x lags matrix
|
|
| 133 | 132 |
% Only the current value is stored |
| 134 |
% sacf is the vertical summary of acf ( a vector) and all values are kept and returned
|
|
| 135 |
% P is the smoothed version of sacf and all values are kept and returned
|
|
| 133 |
% SACF is the vertical sum of ACFs; all values are kept and returned
|
|
| 134 |
% LP_SACF is the smoothed version of SACF:all values are kept and returned
|
|
| 136 | 135 |
% lagWeights emphasise some BF/lag combinations and ignore others |
| 137 | 136 |
% NB time now begins at the longest lag. |
| 138 |
% E.g. if max(lags) is .04 then this is when the ACf will begin. |
|
| 139 |
% AN AN delayed weights filtering |
|
| 140 |
|
|
| 137 |
% E.g. if max(lags) is .04 then this is when the ACf will begin (?). |
|
| 138 |
|
|
| 141 | 139 |
% This is the ACF calculation |
| 142 | 140 |
timeCounter=timeCounter+1; |
| 143 |
acf= (repmat(inputSignalMatrix(:, timePointer), 1, nLags) .* inputSignalMatrix(:, timePointer-lagPointers)).*lagWeights *dt + acf.* acfDecayFactors;
|
|
| 144 |
x=(mean(acf,1)./acfTaus)';
|
|
| 145 |
% disp(num2str(x'))
|
|
| 146 |
sacf(:,timeCounter)=x;
|
|
| 147 |
P(:,timeCounter+1)=sacf(:,timeCounter)*(1-pDecayFactor)+P(:,timeCounter)*pDecayFactor;
|
|
| 141 |
ACF= (repmat(inputSignalMatrix(:, timePointer), 1, nLags) .* ...
|
|
| 142 |
inputSignalMatrix(:, timePointer-lagPointers)).*...
|
|
| 143 |
lagWeights *dt + ACF.* acfDecayFactors;
|
|
| 144 |
x=(mean(ACF,1)./acfTaus)';
|
|
| 145 |
SACF(:,timeCounter)=x;
|
|
| 148 | 146 |
|
| 149 |
% plot at intervals of 200 points |
|
| 150 |
if plotACF && ~mod(timePointer,params.plotACFsInterval) |
|
| 151 |
% mark cursor on chart to signal progress |
|
| 152 |
% this assumes that the user has already plotted |
|
| 153 |
% the signal in subplot(2,1,1) of figure (13) |
|
| 154 |
figure(13) |
|
| 155 |
hold on |
|
| 156 |
subplot(4,1,1) |
|
| 147 |
% smoothed version of SACF |
|
| 148 |
LP_SACF(:,timeCounter+1)=SACF(:,timeCounter)* (1-pDecayFactor) + ... |
|
| 149 |
LP_SACF(:,timeCounter)* pDecayFactor; |
|
| 150 |
|
|
| 151 |
% plot ACF at intervals if requested to do so |
|
| 152 |
if plotACF && ~mod(timePointer,params.plotACFsInterval) && ... |
|
| 153 |
timePointer*dt>3*max(lags) |
|
| 154 |
figure(89), clf |
|
| 155 |
% plot ACFs one per channel |
|
| 156 |
subplot(2,1,1) |
|
| 157 |
UTIL_cascadePlot(ACF, lags) |
|
| 158 |
title(['running ACF at ' num2str(dt*timePointer,'%5.3f') ' s']) |
|
| 159 |
ylabel('channel BF'), xlabel('period (lag, ms)')
|
|
| 160 |
set(gca,'ytickLabel',[]) |
|
| 161 |
|
|
| 162 |
% plot SACF |
|
| 163 |
subplot(4,1,3), cla |
|
| 164 |
plotSACF=SACF(:,timeCounter)-min(SACF(:,timeCounter)); |
|
| 165 |
plot(lags*1000, plotSACF, 'k') |
|
| 166 |
biggestSACF=max(biggestSACF, max(plotSACF)); |
|
| 167 |
if biggestSACF>0, ylim([0 biggestSACF]), else ylim([0 1]), end |
|
| 168 |
ylabel('SACF'), set(gca,'ytickLabel',[])
|
|
| 169 |
% xlim([min(lags*1000) max(lags*1000)]) |
|
| 170 |
|
|
| 171 |
% plot signal |
|
| 172 |
subplot(4,1,4) |
|
| 173 |
plot(signalTime, savedInputSignal, 'k'), hold on |
|
| 174 |
xlim([0 max(signalTime)]) |
|
| 175 |
a= ylim; |
|
| 176 |
% mark cursor on chart to indicate progress |
|
| 157 | 177 |
time=timePointer*dt; |
| 158 |
a =ylim; |
|
| 159 |
plot([time time], [a(1) a(1)+(a(2)-a(1))/4]) % current signal point marker |
|
| 160 |
|
|
| 161 |
% plot ACFs one per channel |
|
| 162 |
subplot(2,1,2), cla |
|
| 163 |
cascadePlot(acf, lags, BFlist) |
|
| 164 |
xlim([min(lags) max(lags)]) |
|
| 165 |
% set(gca,'xscale','log') |
|
| 166 |
title(num2str(method.dt*timePointer)) |
|
| 167 |
ylabel('BF'), xlabel('period (lag)')
|
|
| 168 |
|
|
| 169 |
% plot SACF |
|
| 170 |
subplot(4,1,2), hold off |
|
| 171 |
plot(lags,sacf(:,timeCounter)-min(sacf(:,timeCounter))) |
|
| 172 |
biggestSACF=max(biggestSACF, max(sacf(:,timeCounter))); |
|
| 173 |
if biggestSACF>0, ylim([0 biggestSACF]), end |
|
| 174 |
% set(gca,'xscale','log') |
|
| 175 |
title('SACF')
|
|
| 178 |
plot([time time], [a(1) a(1)+(a(2)-a(1))/4], 'r', 'linewidth', 5) |
|
| 176 | 179 |
pause(params.plotMoviePauses) |
| 177 | 180 |
end |
| 178 | 181 |
end |
| 179 |
P=P(:,1:end-1); % correction for speed up above
|
|
| 182 |
LP_SACF=LP_SACF(:,1:end-1); % correction for speed up above
|
|
| 180 | 183 |
|
| 181 | 184 |
% Pressnitzer weights |
| 182 | 185 |
if ~isfield(params, 'usePressnitzer'), params.usePressnitzer=0; end |
| 183 | 186 |
if params.usePressnitzer |
| 184 |
[a nTimePoints]=size(P);
|
|
| 187 |
[a nTimePoints]=size(LP_SACF);
|
|
| 185 | 188 |
% higher pitches get higher weights |
| 186 | 189 |
% PressnitzerWeights=repmat(min(lags)./lags,nTimePoints,1); |
| 187 | 190 |
% weaker weighting |
| 188 | 191 |
PressnitzerWeights=repmat((min(lags)./lags).^0.5, nTimePoints,1); |
| 189 |
P=P.*PressnitzerWeights';
|
|
| 190 |
sacf=sacf.*PressnitzerWeights';
|
|
| 192 |
LP_SACF=LP_SACF.*PressnitzerWeights';
|
|
| 193 |
SACF=SACF.*PressnitzerWeights';
|
|
| 191 | 194 |
end |
| 192 | 195 |
|
| 193 | 196 |
% wrap up |
| 194 |
method.acfLags=lags; |
|
| 195 |
method.filteredSACFdt=dt; |
|
| 196 |
|
|
| 197 |
boundaryValue{1}=acf(:,end-nLags+1:end);
|
|
| 198 |
boundaryValue{2}=P(:,end);
|
|
| 197 |
% BoundaryValue is legacy programming used in segmented model (keep) |
|
| 198 |
ACFboundaryValue{1}=ACF(:,end-nLags+1:end);
|
|
| 199 |
ACFboundaryValue{2}=LP_SACF(:,end);
|
|
| 199 | 200 |
% save signal buffer for next segment |
| 200 |
boundaryValue{3} = inputSignalMatrix(:, end-max(lagPointers)+1 : end);
|
|
| 201 |
|
|
| 202 |
method.displaydt=method.filteredSACFdt; |
|
| 203 |
|
|
| 204 |
% if ~isfield(params, 'plotUnflteredSACF'), params.plotUnflteredSACF=0; end |
|
| 205 |
% if method.plotGraphs |
|
| 206 |
% method.plotUnflteredSACF=params.plotUnflteredSACF; |
|
| 207 |
% if ~method.plotUnflteredSACF |
|
| 208 |
% method=filteredSACFPlot(P,method); |
|
| 209 |
% else |
|
| 210 |
% method=filteredSACFPlot(SACF,method); |
|
| 211 |
% end |
|
| 212 |
% end |
|
| 213 |
|
|
| 214 |
|
|
| 215 |
% ------------------------------------------------ plotting ACFs |
|
| 216 |
function cascadePlot(toPlot, lags, BFs) |
|
| 217 |
% % useful code |
|
| 218 |
[nChannels nLags]=size(toPlot); |
|
| 219 |
|
|
| 220 |
% cunning code to represent channels as parallel lines |
|
| 221 |
[nRows nCols]=size(toPlot); |
|
| 222 |
if nChannels>1 |
|
| 223 |
% max(toPlot) defines the spacing between lines |
|
| 224 |
a=max(max(toPlot))*(0:nRows-1)'; |
|
| 225 |
% a is the height to be added to each channel |
|
| 226 |
peakGain=10; |
|
| 227 |
% peakGain emphasises the peak height |
|
| 228 |
x=peakGain*toPlot+repmat(a,1,nCols); |
|
| 229 |
x=nRows*x/max(max(x)); |
|
| 230 |
else |
|
| 231 |
x=toPlot; % used when only the stimulus is returned |
|
| 232 |
end |
|
| 233 |
plot(lags, x','k') |
|
| 234 |
ylim([0 nRows]) |
|
| 235 |
|
|
| 201 |
ACFboundaryValue{3} = inputSignalMatrix(:, end-max(lagPointers)+1 : end);
|
|
| MAP/old MAP files/MAP1_14AP.m | ||
|---|---|---|
| 1 |
|
|
| 2 |
function MAP1_14AP(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 vector of BFs but can be '-1' to allow MAPparams to choose |
|
| 9 |
% MAPparamsName='Normal'; % source of model parameters |
|
| 10 |
% AN_spikesOrProbability='spikes'; % or 'probability' |
|
| 11 |
% paramChanges is a cell array of strings that can be used to make last |
|
| 12 |
% minute parameter changes, e.g., to simulate OHC loss |
|
| 13 |
% e.g. paramChanges{1}= 'DRNLParams.a=0;'; % disable OHCs
|
|
| 14 |
% e.g. paramchanges={}; % no changes
|
|
| 15 |
% The model parameters are established in the MAPparams<***> file |
|
| 16 |
% and stored as global |
|
| 17 |
|
|
| 18 |
restorePath=path; |
|
| 19 |
addpath (['..' filesep 'parameterStore']) |
|
| 20 |
|
|
| 21 |
|
|
| 22 |
CONVOLUTION_CHANGE_TEST = 0; %for debug |
|
| 23 |
|
|
| 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 tauCas ... |
|
| 33 |
CNoutput ICoutput ICmembraneOutput ICfiberTypeRates MOCattenuation |
|
| 34 |
|
|
| 35 |
% Normally only ICoutput(logical spike matrix) or ANprobRateOutput will be |
|
| 36 |
% needed by the user; so the following will suffice |
|
| 37 |
% global ANdt ICoutput ANprobRateOutput |
|
| 38 |
|
|
| 39 |
% Note that sampleRate has not changed from the original function call and |
|
| 40 |
% ANprobRateOutput is sampled at this rate |
|
| 41 |
% However ANoutput, CNoutput and IC output are stored as logical |
|
| 42 |
% 'spike' matrices using a lower sample rate (see ANdt). |
|
| 43 |
|
|
| 44 |
% When AN_spikesOrProbability is set to probability, |
|
| 45 |
% no spike matrices are computed. |
|
| 46 |
% When AN_spikesOrProbability is set to 'spikes', |
|
| 47 |
% no probability output is computed |
|
| 48 |
|
|
| 49 |
% Efferent control variables are ARattenuation and MOCattenuation |
|
| 50 |
% These are scalars between 1 (no attenuation) and 0. |
|
| 51 |
% They are represented with dt=1/sampleRate (not ANdt) |
|
| 52 |
% They are computed using either AN probability rate output |
|
| 53 |
% or IC (spikes) output as approrpriate. |
|
| 54 |
% AR is computed using across channel activity |
|
| 55 |
% MOC is computed on a within-channel basis. |
|
| 56 |
|
|
| 57 |
if nargin<1 |
|
| 58 |
error(' MAP1_14 is not a script but a function that must be called')
|
|
| 59 |
end |
|
| 60 |
|
|
| 61 |
if nargin<6 |
|
| 62 |
paramChanges=[]; |
|
| 63 |
end |
|
| 64 |
% Read parameters from MAPparams<***> file in 'parameterStore' folder |
|
| 65 |
% Beware, 'BFlist=-1' is a legitimate argument for MAPparams<> |
|
| 66 |
% It means that the calling program allows MAPparams to specify the list |
|
| 67 |
cmd=['method=MAPparams' MAPparamsName ... |
|
| 68 |
'(BFlist, sampleRate, 0, paramChanges);']; |
|
| 69 |
eval(cmd); |
|
| 70 |
BFlist=DRNLParams.nonlinCFs; |
|
| 71 |
|
|
| 72 |
% save as global for later plotting if required |
|
| 73 |
savedBFlist=BFlist; |
|
| 74 |
saveAN_spikesOrProbability=AN_spikesOrProbability; |
|
| 75 |
saveMAPparamsName=MAPparamsName; |
|
| 76 |
|
|
| 77 |
dt=1/sampleRate; |
|
| 78 |
duration=length(inputSignal)/sampleRate; |
|
| 79 |
% segmentDuration is specified in parameter file (must be >efferent delay) |
|
| 80 |
segmentDuration=method.segmentDuration; |
|
| 81 |
segmentLength=round(segmentDuration/ dt); |
|
| 82 |
segmentTime=dt*(1:segmentLength); % used in debugging plots |
|
| 83 |
|
|
| 84 |
% all spiking activity is computed using longer epochs |
|
| 85 |
ANspeedUpFactor=AN_IHCsynapseParams.ANspeedUpFactor; % e.g.5 times |
|
| 86 |
|
|
| 87 |
% inputSignal must be row vector |
|
| 88 |
[r c]=size(inputSignal); |
|
| 89 |
if r>c, inputSignal=inputSignal'; end % transpose |
|
| 90 |
% ignore stereo signals |
|
| 91 |
inputSignal=inputSignal(1,:); % drop any second channel |
|
| 92 |
savedInputSignal=inputSignal; |
|
| 93 |
|
|
| 94 |
% Segment the signal |
|
| 95 |
% The sgment length is given but the signal length must be adjusted to be a |
|
| 96 |
% multiple of both the segment length and the reduced segmentlength |
|
| 97 |
[nSignalRows signalLength]=size(inputSignal); |
|
| 98 |
segmentLength=ceil(segmentLength/ANspeedUpFactor)*ANspeedUpFactor; |
|
| 99 |
% Make the signal length a whole multiple of the segment length |
|
| 100 |
nSignalSegments=ceil(signalLength/segmentLength); |
|
| 101 |
padSize=nSignalSegments*segmentLength-signalLength; |
|
| 102 |
pad=zeros(nSignalRows,padSize); |
|
| 103 |
inputSignal=[inputSignal pad]; |
|
| 104 |
[ignore signalLength]=size(inputSignal); |
|
| 105 |
|
|
| 106 |
% AN (spikes) is computed at a lower sample rate when spikes required |
|
| 107 |
% so it has a reduced segment length (see 'ANspeeUpFactor' above) |
|
| 108 |
% AN CN and IC all use this sample interval |
|
| 109 |
ANdt=dt*ANspeedUpFactor; |
|
| 110 |
reducedSegmentLength=round(segmentLength/ANspeedUpFactor); |
|
| 111 |
reducedSignalLength= round(signalLength/ANspeedUpFactor); |
|
| 112 |
|
|
| 113 |
%% Initialise with respect to each stage before computing |
|
| 114 |
% by allocating memory, |
|
| 115 |
% by computing constants |
|
| 116 |
% by establishing easy to read variable names |
|
| 117 |
% The computations are made in segments and boundary conditions must |
|
| 118 |
% be established and stored. These are found in variables with |
|
| 119 |
% 'boundary' or 'bndry' in the name |
|
| 120 |
|
|
| 121 |
%% OME --- |
|
| 122 |
% external ear resonances |
|
| 123 |
OMEexternalResonanceFilters=OMEParams.externalResonanceFilters; |
|
| 124 |
[nOMEExtFilters c]=size(OMEexternalResonanceFilters); |
|
| 125 |
% details of external (outer ear) resonances |
|
| 126 |
OMEgaindBs=OMEexternalResonanceFilters(:,1); |
|
| 127 |
OMEgainScalars=10.^(OMEgaindBs/20); |
|
| 128 |
OMEfilterOrder=OMEexternalResonanceFilters(:,2); |
|
| 129 |
OMElowerCutOff=OMEexternalResonanceFilters(:,3); |
|
| 130 |
OMEupperCutOff=OMEexternalResonanceFilters(:,4); |
|
| 131 |
% external resonance coefficients |
|
| 132 |
ExtFilter_b=cell(nOMEExtFilters,1); |
|
| 133 |
ExtFilter_a=cell(nOMEExtFilters,1); |
|
| 134 |
for idx=1:nOMEExtFilters |
|
| 135 |
Nyquist=sampleRate/2; |
|
| 136 |
[b, a] = butter(OMEfilterOrder(idx), ... |
|
| 137 |
[OMElowerCutOff(idx) OMEupperCutOff(idx)]... |
|
| 138 |
/Nyquist); |
|
| 139 |
ExtFilter_b{idx}=b;
|
|
| 140 |
ExtFilter_a{idx}=a;
|
|
| 141 |
end |
|
| 142 |
OMEExtFilterBndry=cell(2,1); |
|
| 143 |
OMEextEarPressure=zeros(1,signalLength); % pressure at tympanic membrane |
|
| 144 |
|
|
| 145 |
% pressure to velocity conversion using smoothing filter (50 Hz cutoff) |
|
| 146 |
tau=1/(2*pi*50); |
|
| 147 |
a1=dt/tau-1; a0=1; |
|
| 148 |
b0=1+ a1; |
|
| 149 |
TMdisp_b=b0; TMdisp_a=[a0 a1]; |
|
| 150 |
% figure(9), freqz(TMdisp_b, TMdisp_a) |
|
| 151 |
OME_TMdisplacementBndry=[]; |
|
| 152 |
|
|
| 153 |
% OME high pass (simulates poor low frequency stapes response) |
|
| 154 |
OMEhighPassHighCutOff=OMEParams.OMEstapesLPcutoff; |
|
| 155 |
Nyquist=sampleRate/2; |
|
| 156 |
[stapesDisp_b,stapesDisp_a] = butter(1, OMEhighPassHighCutOff/Nyquist, 'high'); |
|
| 157 |
% figure(10), freqz(stapesDisp_b, stapesDisp_a) |
|
| 158 |
|
|
| 159 |
OMEhighPassBndry=[]; |
|
| 160 |
|
|
| 161 |
% OMEampStapes might be reducdant (use OMEParams.stapesScalar) |
|
| 162 |
stapesScalar= OMEParams.stapesScalar; |
|
| 163 |
|
|
| 164 |
% Acoustic reflex |
|
| 165 |
efferentDelayPts=round(OMEParams.ARdelay/dt); |
|
| 166 |
% smoothing filter |
|
| 167 |
a1=dt/OMEParams.ARtau-1; a0=1; |
|
| 168 |
b0=1+ a1; |
|
| 169 |
ARfilt_b=b0; ARfilt_a=[a0 a1]; |
|
| 170 |
|
|
| 171 |
ARattenuation=ones(1,signalLength); |
|
| 172 |
ARrateThreshold=OMEParams.ARrateThreshold; % may not be used |
|
| 173 |
ARrateToAttenuationFactor=OMEParams.rateToAttenuationFactor; |
|
| 174 |
ARrateToAttenuationFactorProb=OMEParams.rateToAttenuationFactorProb; |
|
| 175 |
ARboundary=[]; |
|
| 176 |
ARboundaryProb=0; |
|
| 177 |
|
|
| 178 |
% save complete OME record (stapes displacement) |
|
| 179 |
OMEoutput=zeros(1,signalLength); |
|
| 180 |
TMoutput=zeros(1,signalLength); |
|
| 181 |
|
|
| 182 |
%% BM --- |
|
| 183 |
% BM is represented as a list of locations identified by BF |
|
| 184 |
DRNL_BFs=BFlist; |
|
| 185 |
nBFs= length(DRNL_BFs); |
|
| 186 |
|
|
| 187 |
% DRNLchannelParameters=DRNLParams.channelParameters; |
|
| 188 |
DRNLresponse= zeros(nBFs, segmentLength); |
|
| 189 |
|
|
| 190 |
MOCrateToAttenuationFactor=DRNLParams.rateToAttenuationFactor; |
|
| 191 |
rateToAttenuationFactorProb=DRNLParams.rateToAttenuationFactorProb; |
|
| 192 |
MOCrateThresholdProb=DRNLParams.MOCrateThresholdProb; |
|
| 193 |
|
|
| 194 |
% smoothing filter for MOC |
|
| 195 |
a1=dt/DRNLParams.MOCtau-1; a0=1; |
|
| 196 |
b0=1+ a1; |
|
| 197 |
MOCfilt_b=b0; MOCfilt_a=[a0 a1]; |
|
| 198 |
% figure(9), freqz(stapesDisp_b, stapesDisp_a) |
|
| 199 |
MOCboundary=cell(nBFs,1); |
|
| 200 |
MOCprobBoundary=cell(nBFs,1); |
|
| 201 |
|
|
| 202 |
MOCattSegment=zeros(nBFs,reducedSegmentLength); |
|
| 203 |
MOCattenuation=ones(nBFs,signalLength); |
|
| 204 |
|
|
| 205 |
if DRNLParams.a>0 |
|
| 206 |
DRNLcompressionThreshold=10^((1/(1-DRNLParams.c))* ... |
|
| 207 |
log10(DRNLParams.b/DRNLParams.a)); |
|
| 208 |
else |
|
| 209 |
DRNLcompressionThreshold=inf; |
|
| 210 |
end |
|
| 211 |
|
|
| 212 |
DRNLlinearOrder= DRNLParams.linOrder; |
|
| 213 |
DRNLnonlinearOrder= DRNLParams.nonlinOrder; |
|
| 214 |
|
|
| 215 |
DRNLa=DRNLParams.a; |
|
| 216 |
DRNLb=DRNLParams.b; |
|
| 217 |
DRNLc=DRNLParams.c; |
|
| 218 |
linGAIN=DRNLParams.g; |
|
| 219 |
% |
|
| 220 |
% gammatone filter coefficients for linear pathway |
|
| 221 |
bw=DRNLParams.linBWs'; |
|
| 222 |
phi = 2 * pi * bw * dt; |
|
| 223 |
cf=DRNLParams.linCFs'; |
|
| 224 |
theta = 2 * pi * cf * dt; |
|
| 225 |
cos_theta = cos(theta); |
|
| 226 |
sin_theta = sin(theta); |
|
| 227 |
alpha = -exp(-phi).* cos_theta; |
|
| 228 |
b0 = ones(nBFs,1); |
|
| 229 |
b1 = 2 * alpha; |
|
| 230 |
b2 = exp(-2 * phi); |
|
| 231 |
z1 = (1 + alpha .* cos_theta) - (alpha .* sin_theta) * i; |
|
| 232 |
z2 = (1 + b1 .* cos_theta) - (b1 .* sin_theta) * i; |
|
| 233 |
z3 = (b2 .* cos(2 * theta)) - (b2 .* sin(2 * theta)) * i; |
|
| 234 |
tf = (z2 + z3) ./ z1; |
|
| 235 |
a0 = abs(tf); |
|
| 236 |
a1 = alpha .* a0; |
|
| 237 |
GTlin_a = [b0, b1, b2]; |
|
| 238 |
GTlin_b = [a0, a1]; |
|
| 239 |
GTlinOrder=DRNLlinearOrder; |
|
| 240 |
GTlinBdry=cell(nBFs,GTlinOrder); |
|
| 241 |
|
|
| 242 |
% nonlinear gammatone filter coefficients |
|
| 243 |
bw=DRNLParams.nlBWs'; |
|
| 244 |
phi = 2 * pi * bw * dt; |
|
| 245 |
cf=DRNLParams.nonlinCFs'; |
|
| 246 |
theta = 2 * pi * cf * dt; |
|
| 247 |
cos_theta = cos(theta); |
|
| 248 |
sin_theta = sin(theta); |
|
| 249 |
alpha = -exp(-phi).* cos_theta; |
|
| 250 |
b0 = ones(nBFs,1); |
|
| 251 |
b1 = 2 * alpha; |
|
| 252 |
b2 = exp(-2 * phi); |
|
| 253 |
z1 = (1 + alpha .* cos_theta) - (alpha .* sin_theta) * i; |
|
| 254 |
z2 = (1 + b1 .* cos_theta) - (b1 .* sin_theta) * i; |
|
| 255 |
z3 = (b2 .* cos(2 * theta)) - (b2 .* sin(2 * theta)) * i; |
|
| 256 |
tf = (z2 + z3) ./ z1; |
|
| 257 |
a0 = abs(tf); |
|
| 258 |
a1 = alpha .* a0; |
|
| 259 |
GTnonlin_a = [b0, b1, b2]; |
|
| 260 |
GTnonlin_b = [a0, a1]; |
|
| 261 |
GTnonlinOrder=DRNLnonlinearOrder; |
|
| 262 |
GTnonlinBdry1=cell(nBFs, GTnonlinOrder); |
|
| 263 |
GTnonlinBdry2=cell(nBFs, GTnonlinOrder); |
|
| 264 |
|
|
| 265 |
% complete BM record (BM displacement) |
|
| 266 |
DRNLoutput=zeros(nBFs, signalLength); |
|
| 267 |
|
|
| 268 |
|
|
| 269 |
%% IHC --- |
|
| 270 |
% IHC cilia activity and receptor potential |
|
| 271 |
% viscous coupling between BM and stereocilia displacement |
|
| 272 |
% Nyquist=sampleRate/2; |
|
| 273 |
% IHCcutoff=1/(2*pi*IHC_cilia_RPParams.tc); |
|
| 274 |
% [IHCciliaFilter_b,IHCciliaFilter_a]=... |
|
| 275 |
% butter(1, IHCcutoff/Nyquist, 'high'); |
|
| 276 |
a1=dt/IHC_cilia_RPParams.tc-1; a0=1; |
|
| 277 |
b0=1+ a1; |
|
| 278 |
% high pass (i.e. low pass reversed) |
|
| 279 |
IHCciliaFilter_b=[a0 a1]; IHCciliaFilter_a=b0; |
|
| 280 |
% figure(9), freqz(IHCciliaFilter_b, IHCciliaFilter_a) |
|
| 281 |
|
|
| 282 |
IHCciliaBndry=cell(nBFs,1); |
|
| 283 |
|
|
| 284 |
% IHC apical conductance (Boltzman function) |
|
| 285 |
IHC_C= IHC_cilia_RPParams.C; |
|
| 286 |
IHCu0= IHC_cilia_RPParams.u0; |
|
| 287 |
IHCu1= IHC_cilia_RPParams.u1; |
|
| 288 |
IHCs0= IHC_cilia_RPParams.s0; |
|
| 289 |
IHCs1= IHC_cilia_RPParams.s1; |
|
| 290 |
IHCGmax= IHC_cilia_RPParams.Gmax; |
|
| 291 |
IHCGa= IHC_cilia_RPParams.Ga; % (leakage) |
|
| 292 |
|
|
| 293 |
IHCGu0 = IHCGa+IHCGmax./(1+exp(IHCu0/IHCs0).*(1+exp(IHCu1/IHCs1))); |
|
| 294 |
IHCrestingCiliaCond=IHCGu0; |
|
| 295 |
|
|
| 296 |
% Receptor potential |
|
| 297 |
IHC_Cab= IHC_cilia_RPParams.Cab; |
|
| 298 |
IHC_Gk= IHC_cilia_RPParams.Gk; |
|
| 299 |
IHC_Et= IHC_cilia_RPParams.Et; |
|
| 300 |
IHC_Ek= IHC_cilia_RPParams.Ek; |
|
| 301 |
IHC_Ekp= IHC_Ek+IHC_Et*IHC_cilia_RPParams.Rpc; |
|
| 302 |
|
|
| 303 |
IHCrestingV= (IHC_Gk*IHC_Ekp+IHCGu0*IHC_Et)/(IHCGu0+IHC_Gk); |
|
| 304 |
|
|
| 305 |
IHC_Vnow= IHCrestingV*ones(nBFs,1); % initial voltage |
|
| 306 |
IHC_RP= zeros(nBFs,segmentLength); |
|
| 307 |
|
|
| 308 |
% complete record of IHC receptor potential (V) |
|
| 309 |
IHCciliaDisplacement= zeros(nBFs,segmentLength); |
|
| 310 |
IHCoutput= zeros(nBFs,signalLength); |
|
| 311 |
IHC_cilia_output= zeros(nBFs,signalLength); |
|
| 312 |
|
|
| 313 |
|
|
| 314 |
%% pre-synapse --- |
|
| 315 |
% Each BF is replicated using a different fiber type to make a 'channel' |
|
| 316 |
% The number of channels is nBFs x nANfiberTypes |
|
| 317 |
% Fiber types are specified in terms of tauCa |
|
| 318 |
nANfiberTypes= length(IHCpreSynapseParams.tauCa); |
|
| 319 |
tauCas= IHCpreSynapseParams.tauCa; |
|
| 320 |
nANchannels= nANfiberTypes*nBFs; |
|
| 321 |
synapticCa= zeros(nANchannels,segmentLength); |
|
| 322 |
|
|
| 323 |
% Calcium control (more calcium, greater release rate) |
|
| 324 |
ECa=IHCpreSynapseParams.ECa; |
|
| 325 |
gamma=IHCpreSynapseParams.gamma; |
|
| 326 |
beta=IHCpreSynapseParams.beta; |
|
| 327 |
tauM=IHCpreSynapseParams.tauM; |
|
| 328 |
mICa=zeros(nANchannels,segmentLength); |
|
| 329 |
GmaxCa=IHCpreSynapseParams.GmaxCa; |
|
| 330 |
synapse_z= IHCpreSynapseParams.z; |
|
| 331 |
synapse_power=IHCpreSynapseParams.power; |
|
| 332 |
|
|
| 333 |
% tauCa vector is established across channels to allow vectorization |
|
| 334 |
% (one tauCa per channel). Do not confuse with tauCas (one pre fiber type) |
|
| 335 |
tauCa=repmat(tauCas, nBFs,1); |
|
| 336 |
tauCa=reshape(tauCa, nANchannels, 1); |
|
| 337 |
|
|
| 338 |
% presynapse startup values (vectors, length:nANchannels) |
|
| 339 |
% proportion (0 - 1) of Ca channels open at IHCrestingV |
|
| 340 |
mICaCurrent=((1+beta^-1 * exp(-gamma*IHCrestingV))^-1)... |
|
| 341 |
*ones(nBFs*nANfiberTypes,1); |
|
| 342 |
% corresponding startup currents |
|
| 343 |
ICaCurrent= (GmaxCa*mICaCurrent.^3) * (IHCrestingV-ECa); |
|
| 344 |
CaCurrent= ICaCurrent.*tauCa; |
|
| 345 |
|
|
| 346 |
% vesicle release rate at startup (one per channel) |
|
| 347 |
% kt0 is used only at initialisation |
|
| 348 |
kt0= -synapse_z * CaCurrent.^synapse_power; |
|
| 349 |
|
|
| 350 |
|
|
| 351 |
%% AN --- |
|
| 352 |
% each row of the AN matrices represents one AN fiber |
|
| 353 |
% The results computed either for probabiities *or* for spikes (not both) |
|
| 354 |
% Spikes are necessary if CN and IC are to be computed |
|
| 355 |
nFibersPerChannel= AN_IHCsynapseParams.numFibers; |
|
| 356 |
nANfibers= nANchannels*nFibersPerChannel; |
|
| 357 |
AN_refractory_period= AN_IHCsynapseParams.refractory_period; |
|
| 358 |
|
|
| 359 |
y=AN_IHCsynapseParams.y; |
|
| 360 |
l=AN_IHCsynapseParams.l; |
|
| 361 |
x=AN_IHCsynapseParams.x; |
|
| 362 |
r=AN_IHCsynapseParams.r; |
|
| 363 |
M=round(AN_IHCsynapseParams.M); |
|
| 364 |
|
|
| 365 |
% probability (NB initial 'P' on everything) |
|
| 366 |
PAN_ydt = repmat(AN_IHCsynapseParams.y*dt, nANchannels,1); |
|
| 367 |
PAN_ldt = repmat(AN_IHCsynapseParams.l*dt, nANchannels,1); |
|
| 368 |
PAN_xdt = repmat(AN_IHCsynapseParams.x*dt, nANchannels,1); |
|
| 369 |
PAN_rdt = repmat(AN_IHCsynapseParams.r*dt, nANchannels,1); |
|
| 370 |
PAN_rdt_plus_ldt = PAN_rdt + PAN_ldt; |
|
| 371 |
PAN_M=round(AN_IHCsynapseParams.M); |
|
| 372 |
|
|
| 373 |
% compute starting values |
|
| 374 |
Pcleft = kt0* y* M ./ (y*(l+r)+ kt0* l); |
|
| 375 |
Pavailable = Pcleft*(l+r)./kt0; |
|
| 376 |
Preprocess = Pcleft*r/x; % canbe fractional |
|
| 377 |
|
|
| 378 |
ANprobability=zeros(nANchannels,segmentLength); |
|
| 379 |
ANprobRateOutput=zeros(nANchannels,signalLength); |
|
| 380 |
lengthAbsRefractoryP= round(AN_refractory_period/dt); |
|
| 381 |
% special variables for monitoring synaptic cleft (specialists only) |
|
| 382 |
savePavailableSeg=zeros(nANchannels,segmentLength); |
|
| 383 |
savePavailable=zeros(nANchannels,signalLength); |
|
| 384 |
|
|
| 385 |
% spikes % ! ! ! ! ! ! ! ! |
|
| 386 |
lengthAbsRefractory= round(AN_refractory_period/ANdt); |
|
| 387 |
|
|
| 388 |
AN_ydt= repmat(AN_IHCsynapseParams.y*ANdt, nANfibers,1); |
|
| 389 |
AN_ldt= repmat(AN_IHCsynapseParams.l*ANdt, nANfibers,1); |
|
| 390 |
AN_xdt= repmat(AN_IHCsynapseParams.x*ANdt, nANfibers,1); |
|
| 391 |
AN_rdt= repmat(AN_IHCsynapseParams.r*ANdt, nANfibers,1); |
|
| 392 |
AN_rdt_plus_ldt= AN_rdt + AN_ldt; |
|
| 393 |
AN_M= round(AN_IHCsynapseParams.M); |
|
| 394 |
|
|
| 395 |
% kt0 is initial release rate |
|
| 396 |
% Establish as a vector (length=channel x number of fibers) |
|
| 397 |
kt0= repmat(kt0', nFibersPerChannel, 1); |
|
| 398 |
kt0=reshape(kt0, nANfibers,1); |
|
| 399 |
|
|
| 400 |
% starting values for reservoirs |
|
| 401 |
AN_cleft = kt0* y* M ./ (y*(l+r)+ kt0* l); |
|
| 402 |
AN_available = round(AN_cleft*(l+r)./kt0); %must be integer |
|
| 403 |
AN_reprocess = AN_cleft*r/x; |
|
| 404 |
|
|
| 405 |
% output is in a logical array spikes = 1/ 0. |
|
| 406 |
ANspikes= false(nANfibers,reducedSegmentLength); |
|
| 407 |
ANoutput= false(nANfibers,reducedSignalLength); |
|
| 408 |
|
|
| 409 |
|
|
| 410 |
%% CN (first brain stem nucleus - could be any subdivision of CN) |
|
| 411 |
% Input to a CN neuorn is a random selection of AN fibers within a channel |
|
| 412 |
% The number of AN fibers used is ANfibersFanInToCN |
|
| 413 |
% CNtauGk (Potassium time constant) determines the rate of firing of |
|
| 414 |
% the unit when driven hard by a DC input (not normally >350 sp/s) |
|
| 415 |
% If there is more than one value, everything is replicated accordingly |
|
| 416 |
|
|
| 417 |
ANavailableFibersPerChan=AN_IHCsynapseParams.numFibers; |
|
| 418 |
ANfibersFanInToCN=MacGregorMultiParams.fibersPerNeuron; |
|
| 419 |
|
|
| 420 |
CNtauGk=MacGregorMultiParams.tauGk; % row vector of CN types (by tauGk) |
|
| 421 |
nCNtauGk=length(CNtauGk); |
|
| 422 |
|
|
| 423 |
% the total number of 'channels' is now greater |
|
| 424 |
nCNchannels=nANchannels*nCNtauGk; |
|
| 425 |
|
|
| 426 |
nCNneuronsPerChannel=MacGregorMultiParams.nNeuronsPerBF; |
|
| 427 |
tauGk=repmat(CNtauGk, nCNneuronsPerChannel,1); |
|
| 428 |
tauGk=reshape(tauGk,nCNneuronsPerChannel*nCNtauGk,1); |
|
| 429 |
|
|
| 430 |
% Now the number of neurons has been increased |
|
| 431 |
nCNneurons=nCNneuronsPerChannel*nCNchannels; |
|
| 432 |
CNmembranePotential=zeros(nCNneurons,reducedSegmentLength); |
|
| 433 |
|
|
| 434 |
% establish which ANfibers (by name) feed into which CN nuerons |
|
| 435 |
CNinputfiberLists=zeros(nANchannels*nCNneuronsPerChannel, ANfibersFanInToCN); |
|
| 436 |
unitNo=1; |
|
| 437 |
for ch=1:nANchannels |
|
| 438 |
% Each channel contains a number of units =length(listOfFanInValues) |
|
| 439 |
for idx=1:nCNneuronsPerChannel |
|
| 440 |
for idx2=1:nCNtauGk |
|
| 441 |
fibersUsed=(ch-1)*ANavailableFibersPerChan + ... |
|
| 442 |
ceil(rand(1,ANfibersFanInToCN)* ANavailableFibersPerChan); |
|
| 443 |
CNinputfiberLists(unitNo,:)=fibersUsed; |
|
| 444 |
unitNo=unitNo+1; |
|
| 445 |
end |
|
| 446 |
end |
|
| 447 |
end |
|
| 448 |
|
|
| 449 |
% input to CN units |
|
| 450 |
AN_PSTH=zeros(nCNneurons,reducedSegmentLength); |
|
| 451 |
|
|
| 452 |
% Generate CNalphaFunction function |
|
| 453 |
% by which spikes are converted to post-synaptic currents |
|
| 454 |
CNdendriteLPfreq= MacGregorMultiParams.dendriteLPfreq; |
|
| 455 |
CNcurrentPerSpike=MacGregorMultiParams.currentPerSpike; |
|
| 456 |
CNspikeToCurrentTau=1/(2*pi*CNdendriteLPfreq); |
|
| 457 |
t=ANdt:ANdt:5*CNspikeToCurrentTau; |
|
| 458 |
CNalphaFunction= (1 / ... |
|
| 459 |
CNspikeToCurrentTau)*t.*exp(-t /CNspikeToCurrentTau); |
|
| 460 |
CNalphaFunction=CNalphaFunction*CNcurrentPerSpike; |
|
| 461 |
|
|
| 462 |
% figure(98), plot(t,CNalphaFunction) |
|
| 463 |
% working memory for implementing convolution |
|
| 464 |
|
|
| 465 |
CNcurrentTemp=... |
|
| 466 |
zeros(nCNneurons,reducedSegmentLength+length(CNalphaFunction)-1); |
|
| 467 |
% trailing alphas are parts of humps carried forward to the next segment |
|
| 468 |
CNtrailingAlphas=zeros(nCNneurons,length(CNalphaFunction)); |
|
| 469 |
|
|
| 470 |
CN_tauM=MacGregorMultiParams.tauM; |
|
| 471 |
CN_tauTh=MacGregorMultiParams.tauTh; |
|
| 472 |
CN_cap=MacGregorMultiParams.Cap; |
|
| 473 |
CN_c=MacGregorMultiParams.c; |
|
| 474 |
CN_b=MacGregorMultiParams.dGkSpike; |
|
| 475 |
CN_Ek=MacGregorMultiParams.Ek; |
|
| 476 |
CN_Eb= MacGregorMultiParams.Eb; |
|
| 477 |
CN_Er=MacGregorMultiParams.Er; |
|
| 478 |
CN_Th0= MacGregorMultiParams.Th0; |
|
| 479 |
CN_E= zeros(nCNneurons,1); |
|
| 480 |
CN_Gk= zeros(nCNneurons,1); |
|
| 481 |
CN_Th= MacGregorMultiParams.Th0*ones(nCNneurons,1); |
|
| 482 |
CN_Eb=CN_Eb.*ones(nCNneurons,1); |
|
| 483 |
CN_Er=CN_Er.*ones(nCNneurons,1); |
|
| 484 |
CNtimeSinceLastSpike=zeros(nCNneurons,1); |
|
| 485 |
% tauGk is the main distinction between neurons |
|
| 486 |
% in fact they are all the same in the standard model |
|
| 487 |
tauGk=repmat(tauGk,nANchannels,1); |
|
| 488 |
|
|
| 489 |
CNoutput=false(nCNneurons,reducedSignalLength); |
|
| 490 |
|
|
| 491 |
|
|
| 492 |
%% MacGregor (IC - second nucleus) -------- |
|
| 493 |
nICcells=nANchannels*nCNtauGk; % one cell per channel |
|
| 494 |
CN_PSTH=zeros(nICcells ,reducedSegmentLength); |
|
| 495 |
|
|
| 496 |
ICspikeWidth=0.00015; % this may need revisiting |
|
| 497 |
epochsPerSpike=round(ICspikeWidth/ANdt); |
|
| 498 |
if epochsPerSpike<1 |
|
| 499 |
error(['MacGregorMulti: sample rate too low to support ' ... |
|
| 500 |
num2str(ICspikeWidth*1e6) ' microsec spikes']); |
|
| 501 |
end |
|
| 502 |
|
|
| 503 |
% short names |
|
| 504 |
IC_tauM=MacGregorParams.tauM; |
|
| 505 |
IC_tauGk=MacGregorParams.tauGk; |
|
| 506 |
IC_tauTh=MacGregorParams.tauTh; |
|
| 507 |
IC_cap=MacGregorParams.Cap; |
|
| 508 |
IC_c=MacGregorParams.c; |
|
| 509 |
IC_b=MacGregorParams.dGkSpike; |
|
| 510 |
IC_Th0=MacGregorParams.Th0; |
|
| 511 |
IC_Ek=MacGregorParams.Ek; |
|
| 512 |
IC_Eb= MacGregorParams.Eb; |
|
| 513 |
IC_Er=MacGregorParams.Er; |
|
| 514 |
|
|
| 515 |
IC_E=zeros(nICcells,1); |
|
| 516 |
IC_Gk=zeros(nICcells,1); |
|
| 517 |
IC_Th=IC_Th0*ones(nICcells,1); |
|
| 518 |
|
|
| 519 |
% Dendritic filtering, all spikes are replaced by CNalphaFunction functions |
|
| 520 |
ICdendriteLPfreq= MacGregorParams.dendriteLPfreq; |
|
| 521 |
ICcurrentPerSpike=MacGregorParams.currentPerSpike; |
|
| 522 |
ICspikeToCurrentTau=1/(2*pi*ICdendriteLPfreq); |
|
| 523 |
t=ANdt:ANdt:3*ICspikeToCurrentTau; |
|
| 524 |
IC_CNalphaFunction= (ICcurrentPerSpike / ... |
|
| 525 |
ICspikeToCurrentTau)*t.*exp(-t / ICspikeToCurrentTau); |
|
| 526 |
% figure(98), plot(t,IC_CNalphaFunction) |
|
| 527 |
|
|
| 528 |
% working space for implementing alpha function |
|
| 529 |
ICcurrentTemp=... |
|
| 530 |
zeros(nICcells,reducedSegmentLength+length(IC_CNalphaFunction)-1); |
|
| 531 |
ICtrailingAlphas=zeros(nICcells, length(IC_CNalphaFunction)); |
|
| 532 |
|
|
| 533 |
ICfiberTypeRates=zeros(nANfiberTypes,reducedSignalLength); |
|
| 534 |
ICoutput=false(nICcells,reducedSignalLength); |
|
| 535 |
|
|
| 536 |
ICmembranePotential=zeros(nICcells,reducedSegmentLength); |
|
| 537 |
ICmembraneOutput=zeros(nICcells,signalLength); |
|
| 538 |
|
|
| 539 |
|
|
| 540 |
%% Main program %% %% %% %% %% %% %% %% %% %% %% %% %% %% |
|
| 541 |
|
|
| 542 |
% Compute the entire model for each segment |
|
| 543 |
segmentStartPTR=1; |
|
| 544 |
reducedSegmentPTR=1; % when sampling rate is reduced |
|
| 545 |
while segmentStartPTR<signalLength |
|
| 546 |
segmentEndPTR=segmentStartPTR+segmentLength-1; |
|
| 547 |
% shorter segments after speed up. |
|
| 548 |
shorterSegmentEndPTR=reducedSegmentPTR+reducedSegmentLength-1; |
|
| 549 |
|
|
| 550 |
inputPressureSegment=inputSignal... |
|
| 551 |
(:,segmentStartPTR:segmentStartPTR+segmentLength-1); |
|
| 552 |
|
|
| 553 |
% segment debugging plots |
|
| 554 |
% figure(98) |
|
| 555 |
% plot(segmentTime,inputPressureSegment), title('signalSegment')
|
|
| 556 |
|
|
| 557 |
|
|
| 558 |
% OME ---------------------- |
|
| 559 |
|
|
| 560 |
% OME Stage 1: external resonances. Add to inputSignal pressure wave |
|
| 561 |
y=inputPressureSegment; |
|
| 562 |
for n=1:nOMEExtFilters |
|
| 563 |
% any number of resonances can be used |
|
| 564 |
[x OMEExtFilterBndry{n}] = ...
|
|
| 565 |
filter(ExtFilter_b{n},ExtFilter_a{n},...
|
|
| 566 |
inputPressureSegment, OMEExtFilterBndry{n});
|
|
| 567 |
x= x* OMEgainScalars(n); |
|
| 568 |
% This is a parallel resonance so add it |
|
| 569 |
y=y+x; |
|
| 570 |
end |
|
| 571 |
inputPressureSegment=y; |
|
| 572 |
OMEextEarPressure(segmentStartPTR:segmentEndPTR)= inputPressureSegment; |
|
| 573 |
|
|
| 574 |
% OME stage 2: convert input pressure (velocity) to |
|
| 575 |
% tympanic membrane(TM) displacement using low pass filter |
|
| 576 |
[TMdisplacementSegment OME_TMdisplacementBndry] = ... |
|
| 577 |
filter(TMdisp_b,TMdisp_a,inputPressureSegment, ... |
|
| 578 |
OME_TMdisplacementBndry); |
|
| 579 |
% and save it |
|
| 580 |
TMoutput(segmentStartPTR:segmentEndPTR)= TMdisplacementSegment; |
|
| 581 |
|
|
| 582 |
% OME stage 3: middle ear high pass effect to simulate stapes inertia |
|
| 583 |
[stapesDisplacement OMEhighPassBndry] = ... |
|
| 584 |
filter(stapesDisp_b,stapesDisp_a,TMdisplacementSegment, ... |
|
| 585 |
OMEhighPassBndry); |
|
| 586 |
|
|
| 587 |
% OME stage 4: apply stapes scalar |
|
| 588 |
stapesDisplacement=stapesDisplacement*stapesScalar; |
|
| 589 |
|
|
| 590 |
% OME stage 5: acoustic reflex stapes attenuation |
|
| 591 |
% Attenuate the TM response using feedback from LSR fiber activity |
|
| 592 |
if segmentStartPTR>efferentDelayPts |
|
| 593 |
stapesDisplacement= stapesDisplacement.*... |
|
| 594 |
ARattenuation(segmentStartPTR-efferentDelayPts:... |
|
| 595 |
segmentEndPTR-efferentDelayPts); |
|
| 596 |
end |
|
| 597 |
|
|
| 598 |
% segment debugging plots |
|
| 599 |
% figure(98) |
|
| 600 |
% plot(segmentTime, stapesDisplacement), title ('stapesDisplacement')
|
|
| 601 |
|
|
| 602 |
% and save |
|
| 603 |
OMEoutput(segmentStartPTR:segmentEndPTR)= stapesDisplacement; |
|
| 604 |
|
|
| 605 |
|
|
| 606 |
%% BM ------------------------------ |
|
| 607 |
% Each location is computed separately |
|
| 608 |
for BFno=1:nBFs |
|
| 609 |
|
|
| 610 |
% *linear* path |
|
| 611 |
linOutput = stapesDisplacement * linGAIN; % linear gain |
|
| 612 |
for order = 1 : GTlinOrder |
|
| 613 |
[linOutput GTlinBdry{BFno,order}] = ...
|
|
| 614 |
filter(GTlin_b(BFno,:), GTlin_a(BFno,:), linOutput, GTlinBdry{BFno,order});
|
|
Also available in: Unified diff