corrgram.m 5.14 KiB
function [c_out, l_out, t_out] = corrgram(varargin)
%CORRGRAM Calculate windowed cross correlation between two signals.
% C = CORRGRAM(A,B,MAXLAG,WINDOW,NOVERLAP) calculates the windowed cross
% correlation between the signals in vector A and vector B. CORRGRAM splits
% the signals into overlapping segments and forms the columns of C with
% their cross correlation values up to maximum lag specified by scalar
% MAXLAG. Each column of C contains the cross correlation function between
% the short-term, time-localized signals A and B. Time increases linearly
% across the columns of C, from left to right. Lag increases linearly down
% the rows, starting at -MAXLAG. If lengths of A and B differ, the shorter
% signal is filled with zeros. If N is the length of the signals, C is
% a matrix with 2*MAXLAG+1 rows and
% k = fix((N-NOVERLAP)/(WINDOW-NOVERLAP))
% columns.
%
% C = CORRGRAM(...,METHOD) using either Pearson correlation ('pearson', default),
% Spearman's rank correlation ('spearman'), or Kendall's Tau ('kendall').
%
% [C,L,T] = CORRGRAM(...) returns a column of lag L and one of time T
% at which the correlation coefficients are computed. L has length equal
% to the number of rows of C, T has length k.
%
% C = CORRGRAM(A,B) calculates windowed cross correlation using defeault
% settings; the defeaults are MAXLAG = floor(0.1*N), WINDOW = floor(0.1*N)
% and NOVERLAP = 0. You can tell CORRGRAM to use the defeault for any
% parameter by leaving it off or using [] for that parameter, e.g.
% CORRGRAM(A,B,[],1000).
%
% CORRGRAM(A,B) with no output arguments plots the windowed cross
% correlation using the current figure.
%
% Example
% x = cos(0:.01:10*pi)';
% y = sin(0:.01:10*pi)' + .5 * randn(length(x),1);
% corrgram(x,y)
%
% See also CORRCOEF, CORR, XCORR, MIGRAM.
% Copyright (c) 2008-
% Norbert Marwan, Potsdam Institute for Climate Impact Research, Germany
% http://www.pik-potsdam.de
%
% Copyright (c) 2007-2008
% Norbert Marwan, Potsdam University, Germany
% http://www.agnld.uni-potsdam.de
%
% $Date$
% $Revision$
narginchk(2,5)
verbose = 1;
x = varargin{1}; y = varargin{2};
x = x(:); y = y(:);
% check input and inital setting of parameters
nx = length(x); ny = length(y);
if nx < ny % zero-pad x if it has length less than y
x(ny) = 0; nx = ny;
end
if ny < nx % zero-pad y if it has length less than x
y(nx) = 0;
end
maxlag = floor(nx/10);
window = floor(nx/10);
noverlap = 0;
if length(varargin) > 2 & ~isempty(varargin{3}) & isnumeric(varargin{3})
maxlag = varargin{3};
if maxlag < 0, error('Requires positive integer value for maximum lag.'), end
if length(maxlag) > 1, error('Requires MAXLAG to be a scalar.'), end
end
if length(varargin) > 3 & ~isempty(varargin{4}) & isnumeric(varargin{4})
window = varargin{4};
if window < 0, error('Requires positive integer value for window length.'), end
if length(window) > 1, error('Requires WINDOW to be a scalar.'), end
end
if length(varargin) > 4 & ~isempty(varargin{5}) & isnumeric(varargin{5})
noverlap = varargin{5};
if noverlap < 0, error('Requires positive integer value for NOVERLAP.'), end
if length(noverlap) > 1, error('Requires NOVERLAP to be a scalar.'), end
if noverlap >= window, error('Requires NOVERLAP to be strictly less than the window length.'), end
end
% check for input arguments of type char
method = 'Pearson';
i_char = find(cellfun('isclass',varargin,'char'));
if ~isempty(i_char)
method = varargin{i_char}
end
% prepare time delayed signals
X = buffer(x,maxlag+1,maxlag)';
Y = fliplr(buffer(y,maxlag+1,maxlag)');
% divide the delayed signals into overlapping windows
% and compute the correlation coefficient
cnt = 1;
warning off
C = zeros(2*maxlag+1, fix((nx-noverlap)/(window-noverlap)));
if verbose, h = waitbar(0,'Compute cross correlation'); end
% -MAXLAG:0
[Yi dummy] = buffer(Y(:,1),window,noverlap,'nodelay');
Yi = zscore(Yi);
for i = 1:size(X,2), if verbose, waitbar(cnt/(2*size(X,2))), end
[Xi dummy] = buffer(X(:,i),window,noverlap,'nodelay');
Xi = zscore(Xi);
%C(cnt,:) = mean(Xi .* Yi);
C_ = corr(Xi, Yi, 'Type', method);
C(cnt,:) = diag(C_)';
cnt = cnt + 1;
end
% 0:MAXLAG
[Xi dummy] = buffer(X(:,end),window,noverlap,'nodelay');
Xi = zscore(Xi);
for i = 2:size(Y,2), if verbose, waitbar(cnt/(2*size(X,2))), end
[Yi dummy] = buffer(Y(:,i),window,noverlap,'nodelay');
Yi = zscore(Yi);
%C(cnt,:) = mean(Xi .* Yi);
C_ = corr(Xi, Yi, 'Type', method);
C(cnt,:) = diag(C_)';
cnt = cnt + 1;
end
if verbose, delete(h), end
warning on
% create time scale for the windows
t = (1:nx/size(Xi,2):nx)';
l = (-maxlag:maxlag)';
% display and output result
if nargout == 0
newplot
imagesc(t, l, C)
xlabel('Time'), ylabel('Lag'), axis xy
title('Windowed cross correlation', 'fontweight', 'bold')
colorbar
elseif nargout == 1,
c_out = C;
elseif nargout == 2,
c_out = C;
l_out = l;
elseif nargout == 3,
c_out = C;
l_out = l;
t_out = t;
end
function Y = normalize(X)
Y = X - repmat(mean(X), size(X,1), 1);
s = sqrt( sum(conj(Y) .* Y) / (size(Y,1) - 1) );
Y = Y ./ repmat(s, size(Y,1), 1);