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 @ 0:f233164f4c86

History | View | Annotate | Download (8.32 KB)

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).
6
%
7
% INPUT
8
%  	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
%   
13
% 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
17
%   	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
%
24
%
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)
29

    
30
%%
31
boundaryValue=[];
32
[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

    
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
46
if isfield(params, 'plotACFs') && params.plotACFs==1
47
    plotACF=1;
48
else
49
    plotACF=0;  % default
50
end
51

    
52
if isfield(params,'lags')
53
    lags=params.lags;
54
else
55
    lags=params.minLag:params.lagStep:params.maxLag;
56
end
57
nLags=length(lags);
58

    
59
% Establish lag weightsaccording to params.lagsProcedure
60
%  lagWeights allow some lag computations to be ignored
61
%  lagWeights is a (channel x lag) matrix;
62
if isfield(params, 'lagsProcedure')
63
    lagsProcedure=params.lagsProcedure;
64
else
65
    lagsProcedure='useAllLags';  % default
66
end
67
% disp(['lag procedure= ''' lagsProcedure ''''])
68
lagWeights=ones(nChannels,nLags);
69
switch lagsProcedure
70
    case 'useAllLags'
71
       % no action required lagWeights set above
72
    case 'omitShortLags'
73
        % remove lags that are short relative to CF
74
        allLags=repmat(lags,nChannels,1);
75
        allCFs=repmat(BFlist',1,nLags);
76
        criterionForOmittingLags=1./(params.criterionForOmittingLags*allCFs);
77
        idx= allLags < criterionForOmittingLags;	% ignore these lags
78
        lagWeights(idx)=0;
79
    case 'useBernsteinLagWeights'
80
        lagWeights=BernsteinLags(BFlist, lags)';
81
    otherwise
82
        error ('acf: params.lagProcedure not recognised')
83
end
84

    
85

    
86
% Establish matrix of lag time constants 
87
%   these are all the same if tau<1
88
% if acfTau>1, it is assumed that we are using the Wiegrebe method
89
%   and a different decay factor is applied to each lag
90
%   ( i.e., longer lags have longer time constants)
91
acfTau=params.acfTau;
92
if acfTau<1          % all taus are the same
93
    acfTaus=repmat(acfTau, 1, nLags);
94
    acfDecayFactors=ones(size(lags)).*exp(-dt/acfTau);
95
else                      % use Wiegrebe method: tau= 2*lag (for example)
96
    WiegrebeFactor=acfTau;
97
    acfTaus=WiegrebeFactor*lags;
98
    idx= acfTaus<0.0025; acfTaus(idx)=0.0025;
99
    acfDecayFactors= exp(-dt./(acfTaus));
100
end
101
% make acfDecayFactors into a (channels x lags) matrix for speedy computation
102
acfDecayFactors=repmat(acfDecayFactors,nChannels, 1);
103

    
104
% P function lowpass filter decay (only one value needed)
105
pDecayFactor=exp(-dt/params.lambda);
106

    
107
% ACF
108
% lagPointers is a list of pointers relative to 'time now'
109
lagPointers=round(lags/dt);
110
if max(lagPointers)+1>inputLength
111
    error([' filteredSACF: not enough signal to evaluate ACF. Max(lag)= ' num2str(max(lags))])
112
end
113

    
114

    
115
P=zeros(nLags,inputLength+1);   % P must match segment length +1
116
sacf=zeros(nLags,inputLength);
117
if   ~isfield(method,'segmentNumber') || method.segmentNumber==1
118
    acf=zeros(nChannels,nLags);
119
    % create a runup buffer of signal
120
    buffer= zeros(nChannels, max(lagPointers));
121
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};
126
end
127
inputSignalMatrix=[buffer inputSignalMatrix];
128
[nChannels inputLength]= size(inputSignalMatrix);
129

    
130
timeCounter=0; biggestSACF=0;
131
for timePointer= max(lagPointers)+1:inputLength
132
    % acf is a continuously changing channels x lags matrix
133
    %   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
136
    % lagWeights emphasise some BF/lag combinations and ignore others
137
    % 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
    
141
    % This is the ACF calculation
142
    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;
148
    
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)
157
        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')
176
        pause(params.plotMoviePauses)
177
    end
178
end
179
P=P(:,1:end-1);  % correction for speed up above
180

    
181
% Pressnitzer weights
182
if ~isfield(params, 'usePressnitzer'),     params.usePressnitzer=0; end
183
if params.usePressnitzer
184
    [a nTimePoints]=size(P);
185
    % higher pitches get higher weights
186
    %     PressnitzerWeights=repmat(min(lags)./lags,nTimePoints,1);
187
    % weaker weighting
188
    PressnitzerWeights=repmat((min(lags)./lags).^0.5, nTimePoints,1);
189
    P=P.*PressnitzerWeights';
190
    sacf=sacf.*PressnitzerWeights';
191
end
192

    
193
% wrap up
194
method.acfLags=lags;
195
method.filteredSACFdt=dt;
196

    
197
boundaryValue{1}=acf(:,end-nLags+1:end);
198
boundaryValue{2}=P(:,end);
199
% 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