diff --git a/crp_man.pdf b/crp_man.pdf index 292d73241ea4d5703dac4b58c45f68fca5181673..5435c769a3c92f778a19e7887b5ba0322aa7951f 100755 Binary files a/crp_man.pdf and b/crp_man.pdf differ diff --git a/mi.m b/mi.m index b88736459e384e5174e7876ba3ee88ae77afacd4..52ab061465177585ce6d497db5f562c5e3b57628 100644 --- a/mi.m +++ b/mi.m @@ -7,13 +7,13 @@ function varargout=mi(varargin) % between all pairs of X1,X2,...,Xn using 10 bins. The result I % is a N x N matrix. % -% I=MI(X1,X2,...,Xn,N), where N is a scalar, determines the number -% of bins N. -% % I=MI(X1,X2,...,Xn,L) or I=MI(X1,X2,...,Xn,N,L), where L is a % scalar, computes mutual informations for shifting of the % components of each pair of X1,X2,...,Xn until a maximal lag L. % +% I=MI(X1,X2,...,Xn,N,L), where N is a scalar determining the number +% of bins N. +% % [I S]=MI(...) computes the mutual information and the % standard error (only for one- and two-dimensional data). % @@ -60,6 +60,10 @@ function varargout=mi(varargin) % $Revision$ % % $Log$ +% Revision 3.18 2016/03/03 14:57:40 marwan +% updated input/output check (because Mathworks is removing downwards compatibility) +% bug in crqad_big fixed (calculation of xcf). +% % Revision 3.17 2016/02/05 17:16:37 marwan % fix compatibility issues (R2014b) % diff --git a/recons.m b/recons.m index a4d387da0dac7d255818d3b0214ff3bf6de682c8..bb9f367f0461eaba36524aced06bd2892c2cd9a0 100644 --- a/recons.m +++ b/recons.m @@ -3,12 +3,20 @@ function varargout=recons(varargin) % Y = RECONS(X) reconstructs a time series Y from the % recurrence plot in the matrix X. % -% Y = RECONS(X,NAME) reconstructs the time series using +% Y = RECONS(X,...,METHOD) specifies the reconstruction method +% where string METHOD can be either 'thiel' or 'hirata', using +% the method by Marco Thiel (defeault) or Yoshito Hirata. +% +% Y = RECONS(X,...,NAME) reconstructs the time series using % the named cumulative distribution function, which can -% be 'norm' or 'Normal' (defeault), 'unif' or 'Uniform'. +% be 'norm' or 'Normal' (defeault), 'unif' or 'Uniform'. This +% is only necessary for the method by Thiel. The reconstruction +% from the Hirata will not be scaled. % -% Y = RECONS(X,P) reconstructs the time series using -% the cumulative distribution function given by vector P. +% Y = RECONS(X,P,...) reconstructs the time series using the +% cumulative distribution function given by vector P (should be +% 2nd argument). This is only necessary for the method by Thiel. +% The reconstruction from the Hirata will not be scaled. % % See also CRP, CRP2, JRP, TWINSURR. % @@ -16,6 +24,10 @@ function varargout=recons(varargin) % Thiel, M., Romano, M. C., Kurths, J.: % How much information is contained in a recurrence plot?, % Phys. Lett. A, 330, 2004. +% Hirata, Y., Horai, S., Aihara, K.: +% Reproduction of distance matrices from recurrence plots +% and its applications, +% Eur. Phys. J. ST, 164, 2008. % Copyright (c) 2008- % Norbert Marwan, Potsdam Institute for Climate Impact Research, Germany @@ -29,6 +41,10 @@ function varargout=recons(varargin) % $Revision$ % % $Log$ +% Revision 5.4 2016/03/03 14:57:40 marwan +% updated input/output check (because Mathworks is removing downwards compatibility) +% bug in crqad_big fixed (calculation of xcf). +% % Revision 5.3 2009/03/24 08:34:10 marwan % copyright address changed % @@ -50,7 +66,7 @@ function varargout=recons(varargin) errcode = 0; %xout = []; -narginchk(1,2) +narginchk(1,3) nargoutchk(0,1) if isnumeric(varargin{1})==1 % read RP @@ -65,119 +81,172 @@ N = size(X); maxN = prod(N)+1; if N(1) ~= N(2) error('Input must be square matrix.') end +N = N(1); try + % final distribution errcode = 1; -i=(-5:10/(N(1)-1):5)'; -fs=cumsum(10*(1/(sqrt(2*pi))).*exp(-(i).^2./2)); -P=interp1(fs,i,[1:length(fs)],'nearest')'; +i = (-5:10/(N-1):5)'; +fs = cumsum(10*(1/(sqrt(2*pi))).*exp(-(i).^2./2)); +P = interp1(fs,i,[1:length(fs)],'nearest')'; + +% check for input arguments of type char +method = 1; % default reconstruction method by Thiel +i_char = find(cellfun('isclass',varargin,'char')); +for i = i_char + if strcmpi(varargin{i}(1:3), 'thi') + method = 1; + disp('Use reconstruction by Thiel.') + end + if strcmpi(varargin{i}(1:3), 'hir') + method = 2; + disp('Use reconstruction by Hirata') + end + if strcmpi(varargin{i}(1:3), 'uni') + P = (0:1/(N-1):1)'; + disp('Use uniform distribution.') + end +end if nargin > 1 & isnumeric(varargin{2})==1 P = varargin{2}; -elseif nargin > 1 & ischar(varargin{2})==1 - if strcmpi(varargin{2}(1:3), 'uni') - P = (0:1/(N(1)-1):1)'; - disp('uni') - end end P(isnan(P)) = []; % remove NaN from distribution +h_waitbar = waitbar(0,'Reconstruct trajectory'); drawnow -h_waitbar = waitbar(0,'Remove double columns'); drawnow +% number of non-neighbours -% remove double rows -errcode = 2; -[X2 uniI J]=unique(X,'rows'); -uniI = sort(uniI); +if method == 2; +%%%%% Method by Hirata + % calculate weights + waitbar(0, h_waitbar, 'Calculate weights'); drawnow + W = 10000*ones(N,N); + errcode = 3; + for i = 1:N, waitbar(i/N) + neighb = find(X(i,:)); % neighbours of i + % number of intersections + Ninter = sum(X(neighb,:).*repmat(X(i,:),length(neighb),1),2); + % number of union + Nunion = sum((X(neighb,:)+repmat(X(i,:),length(neighb),1))>0,2); + W(i, neighb) = (1 - Ninter./Nunion)'; + end -% this are the removed rows -rem = setdiff(1:length(X2),uniI); -%X3(rem,:) = X(rem,:); + % shortest path + dists = zeros(N,N); + waitbar(0, h_waitbar, 'Calculate shortest paths'); drawnow + for i = 1:N, waitbar(i/N) + sds = dijkstra(W,i); + dists(i,:) = sds; + end -% this are the corresponding columns -for i = 1:length(rem), waitbar(i/length(rem)) -% [dummy, dblI(i), a2] = intersect(X, X(rem(i),:), 'rows'); - X2 = X; - X2(rem,:) = -1; - dblI(i) = find(all((X2 == repmat(X(rem(i),:), size(X2,2), 1))')); -end -% number of non-neighbours -errcode = 3; - -waitbar(0, h_waitbar, 'Search neighbours'); drawnow -NN = maxN*ones(N); -%N = zeros(size(X1)); -for i = 1:size(X,1), waitbar(i/size(X,1)) - if ~ismember(i,rem) - % indices of RPs at i - I = find(X(i,:)); - I(ismember(I,rem)) = []; - - % number of non-neighbours - n = sum((X(I,:) - repmat(X(i,:),length(I),1)) == 1,2); - NN(i,I) = n'; + r = cmdscale(dists); + xneu = r(:,1); + + +else + +%%%%% Method by Thiel + + % remove double rows + errcode = 2; + [X2 uniI J]=unique(X,'rows'); + uniI = sort(uniI); + + % this are the removed rows + rem = setdiff(1:length(X2),uniI); + %X3(rem,:) = X(rem,:); + + % this are the corresponding columns + for i = 1:length(rem), waitbar(i/length(rem)) + % [dummy, dblI(i), a2] = intersect(X, X(rem(i),:), 'rows'); + X2 = X; + X2(rem,:) = -1; + dblI(i) = find(all((X2 == repmat(X(rem(i),:), size(X2,2), 1))')); end - -end -errcode = 4; - -% remove entries on the main diagonal in N -i(1:size(NN,1)) = 1; NN(find(diag(i))) = maxN; - -% determine the both indices where N == 0 for all i -iNaN = NN == maxN; i = find(iNaN); NN2 = NN; NN2(i) = zeros(size(i)); % remove NaNs -n = sum(NN2,1); -borderI=find(n==0); -borderI(ismember(borderI,rem)) = []; - -k = borderI(1); -r = k; % start point in the rank order vector - -errcode = 5; -waitbar(0, h_waitbar, 'Reconstructing time series'); drawnow -while min(NN(:)) < maxN - % look for the minimal N(k,:) - waitbar(length(r)/N(1)) - [dummy kneu] = min(NN(k,:)); - if ~isempty(dummy) kneu = find(NN(k,:) == dummy); else break, end - if length(kneu) > 1 % if a set of minimal N exist - [dummy kneu_index] = min(NN(kneu,k)); - kneu=kneu(kneu_index); + + % number of non-neighbours + errcode = 3; + + waitbar(0, h_waitbar, 'Search neighbours'); drawnow + NN = maxN*ones(N); + %N = zeros(size(X1)); + for i = 1:size(X,1), waitbar(i/size(X,1)) + if ~ismember(i,rem) + % indices of RPs at i + I = find(X(i,:)); + I(ismember(I,rem)) = []; + + % number of non-neighbours + n = sum((X(I,:) - repmat(X(i,:),length(I),1)) == 1,2); + NN(i,I) = n'; + end + end - NN(:,k) = maxN; - kold = k; - k=kneu; - r = [r; k]; % add the new found index to the rank order vector - if length(r) > N(1) + 1 - delete(h_waitbar) - disp(['Critical abort. Could not find enough corresponding neigbours.',10,'Perhaps the recurrence threshold is too small.']) - if nargout - varargout{1} = NaN; + errcode = 4; + + % remove entries on the main diagonal in N + i(1:size(NN,1)) = 1; NN(find(diag(i))) = maxN; + + % determine the both indices where N == 0 for all i + iNaN = NN == maxN; i = find(iNaN); NN2 = NN; NN2(i) = zeros(size(i)); % remove NaNs + n = sum(NN2,1); + borderI=find(n==0); + borderI(ismember(borderI,rem)) = []; + + k = borderI(1); + r = k; % start point in the rank order vector + + errcode = 5; + waitbar(0, h_waitbar, 'Reconstructing time series'); drawnow + while min(NN(:)) < maxN + % look for the minimal N(k,:) + waitbar(length(r)/N(1)) + [dummy kneu] = min(NN(k,:)); + if ~isempty(dummy) kneu = find(NN(k,:) == dummy); else break, end + if length(kneu) > 1 % if a set of minimal N exist + [dummy kneu_index] = min(NN(kneu,k)); + kneu=kneu(kneu_index); + end + NN(:,k) = maxN; + kold = k; + k=kneu; + r = [r; k]; % add the new found index to the rank order vector + if length(r) > N(1) + 1 + delete(h_waitbar) + disp(['Critical abort. Could not find enough corresponding neigbours.',10,'Perhaps the recurrence threshold is too small.']) + if nargout + varargout{1} = NaN; + end + return end - return + end - -end -errcode = 6; -% adjust length of the distribution -P = interp1((1:length(P))/length(P), P, (1:length(r))/length(r),'cubic'); -% assign the distribution to the rank order series -waitbar(0, h_waitbar, 'Assigning distribution'); drawnow -clear xneu -for i = 1:length(r); - xneu(r(i)) = P(i); - waitbar(i/length(r)) -end -errcode = 7; -% add the removed (doubled) elements -for i =1:length(rem) - xneu(rem(i)) = xneu(dblI(i)); + errcode = 6; + % adjust length of the distribution + P = interp1((1:length(P))/length(P), P, (1:length(r))/length(r),'cubic'); + + % assign the distribution to the rank order series + waitbar(0, h_waitbar, 'Assigning distribution'); drawnow + clear xneu + for i = 1:length(r); + xneu(r(i)) = P(i); + waitbar(i/length(r)) + end + + errcode = 7; + + % add the removed (doubled) elements + for i =1:length(rem) + xneu(rem(i)) = xneu(dblI(i)); + end + end delete(h_waitbar) @@ -248,3 +317,53 @@ catch end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function sds = dijkstra(dm, s) +% DIJSKSTRA Shortest path for weighted graph. +% SDS = DIJKSTRA(DM, S) calculates the shortest paths +% from vertex S to all other vertices of the graph DM. + +%DMAX = length(dm) + 1; +DMAX = 100001; + +n = size(dm,1); +visited = zeros(1,n); + +% allocate 1 at the starting node and DMAX for the rest. + +visited = zeros(n,1); +sds = DMAX * ones(n,1); +sds(s) = 0; + +c = n-1; + +while(c > 0) + % find the shortest path among not-visited nodes. + j = 1; + while (visited(j) == 1) + j = j+1; + end + dmin = sds(j); + k = j; + for i=j:n + if(visited(i) == 0) + if(dmin > sds(i)) + dmin = sds(i); + k = i; + end + end + end + + visited(k) = 1; + c = c - 1; +% [c k] + + % find nodes connected to k and increment + for i=1:n + if((visited(i) == 0)&(dm(k,i) >= 0)) + if (sds(i) > sds(k) + dm(k,i)) + sds(i) = sds(k) + dm(k,i); + end + end + end +end +