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

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

Statistics Download as Zip
| Branch: | Revision:

root / MAP / filteredSACF.m @ 38:c2204b18f4a2

History | View | Annotate | Download (7.29 KB)

1 38:c2204b18f4a2 rmeddis
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
%
8 0:f233164f4c86 rmeddis
%
9
% INPUT
10
%  	inputSignalMatrix: a matrix (channel x time) of AN activity
11 38:c2204b18f4a2 rmeddis
%  	dt:		the signal sampling interval in seconds
12
%   BFlist: channel BFs
13
%
14 0:f233164f4c86 rmeddis
% params: 	a list of parmeters to guide the computation:
15 38:c2204b18f4a2 rmeddis
%   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
18 0:f233164f4c86 rmeddis
%   	for calculating tau is to be used (see below)
19 38:c2204b18f4a2 rmeddis
%   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 0:f233164f4c86 rmeddis
%
25
% OUTPUT
26 38:c2204b18f4a2 rmeddis
%  	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.
34 0:f233164f4c86 rmeddis
35
%%
36 38:c2204b18f4a2 rmeddis
global savedInputSignal
37
38
ACFboundaryValue=[];
39
40 0:f233164f4c86 rmeddis
[nChannels inputLength]= size(inputSignalMatrix);
41
42 38:c2204b18f4a2 rmeddis
% create ACF movie
43 0:f233164f4c86 rmeddis
if isfield(params, 'plotACFs') && params.plotACFs==1
44
    plotACF=1;
45 38:c2204b18f4a2 rmeddis
    signalTime=dt:dt:dt*length(savedInputSignal);
46 0:f233164f4c86 rmeddis
else
47
    plotACF=0;  % default
48
end
49 38:c2204b18f4a2 rmeddis
params.plotACFsInterval=round(params.plotACFsInterval/dt);
50 0:f233164f4c86 rmeddis
51
if isfield(params,'lags')
52
    lags=params.lags;
53
else
54
    lags=params.minLag:params.lagStep:params.maxLag;
55
end
56
nLags=length(lags);
57
58
% Establish lag weightsaccording to params.lagsProcedure
59
%  lagWeights allow some lag computations to be ignored
60
%  lagWeights is a (channel x lag) matrix;
61
if isfield(params, 'lagsProcedure')
62
    lagsProcedure=params.lagsProcedure;
63
else
64
    lagsProcedure='useAllLags';  % default
65
end
66 38:c2204b18f4a2 rmeddis
67 0:f233164f4c86 rmeddis
lagWeights=ones(nChannels,nLags);
68
switch lagsProcedure
69
    case 'useAllLags'
70 38:c2204b18f4a2 rmeddis
        % no action required lagWeights set above
71 0:f233164f4c86 rmeddis
    case 'omitShortLags'
72
        % remove lags that are short relative to CF
73
        allLags=repmat(lags,nChannels,1);
74
        allCFs=repmat(BFlist',1,nLags);
75
        criterionForOmittingLags=1./(params.criterionForOmittingLags*allCFs);
76
        idx= allLags < criterionForOmittingLags;	% ignore these lags
77
        lagWeights(idx)=0;
78
    otherwise
79 38:c2204b18f4a2 rmeddis
        error ('ACF: params.lagProcedure not recognised')
80 0:f233164f4c86 rmeddis
end
81
82
83 38:c2204b18f4a2 rmeddis
% Establish matrix of lag time constants
84 0:f233164f4c86 rmeddis
%   these are all the same if tau<1
85
% if acfTau>1, it is assumed that we are using the Wiegrebe method
86
%   and a different decay factor is applied to each lag
87
%   ( i.e., longer lags have longer time constants)
88
acfTau=params.acfTau;
89
if acfTau<1          % all taus are the same
90
    acfTaus=repmat(acfTau, 1, nLags);
91
    acfDecayFactors=ones(size(lags)).*exp(-dt/acfTau);
92 38:c2204b18f4a2 rmeddis
else                  % use Wiegrebe method: tau= 2*lag (for example)
93 0:f233164f4c86 rmeddis
    WiegrebeFactor=acfTau;
94
    acfTaus=WiegrebeFactor*lags;
95
    idx= acfTaus<0.0025; acfTaus(idx)=0.0025;
96
    acfDecayFactors= exp(-dt./(acfTaus));
97
end
98
% make acfDecayFactors into a (channels x lags) matrix for speedy computation
99
acfDecayFactors=repmat(acfDecayFactors,nChannels, 1);
100
101 38:c2204b18f4a2 rmeddis
% LP_SACF function lowpass filter decay (only one value needed)
102 0:f233164f4c86 rmeddis
pDecayFactor=exp(-dt/params.lambda);
103
104
% ACF
105
% lagPointers is a list of pointers relative to 'time now'
106
lagPointers=round(lags/dt);
107
if max(lagPointers)+1>inputLength
108
    error([' filteredSACF: not enough signal to evaluate ACF. Max(lag)= ' num2str(max(lags))])
109
end
110
111
112 38:c2204b18f4a2 rmeddis
LP_SACF=zeros(nLags,inputLength+1);   % LP_SACF must match segment length +1
113
SACF=zeros(nLags,inputLength);
114
method=[];  % legacy programming
115 0:f233164f4c86 rmeddis
if   ~isfield(method,'segmentNumber') || method.segmentNumber==1
116 38:c2204b18f4a2 rmeddis
    ACF=zeros(nChannels,nLags);
117 0:f233164f4c86 rmeddis
    % create a runup buffer of signal
118
    buffer= zeros(nChannels, max(lagPointers));
119
else
120 38:c2204b18f4a2 rmeddis
    % 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};
125 0:f233164f4c86 rmeddis
end
126
inputSignalMatrix=[buffer inputSignalMatrix];
127
[nChannels inputLength]= size(inputSignalMatrix);
128
129
timeCounter=0; biggestSACF=0;
130
for timePointer= max(lagPointers)+1:inputLength
131 38:c2204b18f4a2 rmeddis
    % ACF is a continuously changing channels x lags matrix
132 0:f233164f4c86 rmeddis
    %   Only the current value is stored
133 38:c2204b18f4a2 rmeddis
    % 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
135 0:f233164f4c86 rmeddis
    % lagWeights emphasise some BF/lag combinations and ignore others
136
    % NB time now begins at the longest lag.
137 38:c2204b18f4a2 rmeddis
    % E.g. if max(lags) is .04 then this is when the ACf will begin (?).
138
139 0:f233164f4c86 rmeddis
    % This is the ACF calculation
140
    timeCounter=timeCounter+1;
141 38:c2204b18f4a2 rmeddis
    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;
146 0:f233164f4c86 rmeddis
147 38:c2204b18f4a2 rmeddis
    % 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
177 0:f233164f4c86 rmeddis
        time=timePointer*dt;
178 38:c2204b18f4a2 rmeddis
        plot([time time], [a(1) a(1)+(a(2)-a(1))/4], 'r', 'linewidth', 5)
179 0:f233164f4c86 rmeddis
        pause(params.plotMoviePauses)
180
    end
181
end
182 38:c2204b18f4a2 rmeddis
LP_SACF=LP_SACF(:,1:end-1);  % correction for speed up above
183 0:f233164f4c86 rmeddis
184
% Pressnitzer weights
185
if ~isfield(params, 'usePressnitzer'),     params.usePressnitzer=0; end
186
if params.usePressnitzer
187 38:c2204b18f4a2 rmeddis
    [a nTimePoints]=size(LP_SACF);
188 0:f233164f4c86 rmeddis
    % higher pitches get higher weights
189
    %     PressnitzerWeights=repmat(min(lags)./lags,nTimePoints,1);
190
    % weaker weighting
191
    PressnitzerWeights=repmat((min(lags)./lags).^0.5, nTimePoints,1);
192 38:c2204b18f4a2 rmeddis
    LP_SACF=LP_SACF.*PressnitzerWeights';
193
    SACF=SACF.*PressnitzerWeights';
194 0:f233164f4c86 rmeddis
end
195
196
% wrap up
197 38:c2204b18f4a2 rmeddis
% BoundaryValue is legacy programming used in segmented model (keep)
198
ACFboundaryValue{1}=ACF(:,end-nLags+1:end);
199
ACFboundaryValue{2}=LP_SACF(:,end);
200 0:f233164f4c86 rmeddis
% save signal buffer for next segment
201 38:c2204b18f4a2 rmeddis
ACFboundaryValue{3} = inputSignalMatrix(:, end-max(lagPointers)+1 : end);