function [eig_val,eig_vec,PC,RC,RCp]=SSA(X,varargin)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function SSA : performs Singular Spectrum Analysis on time series X
%       with the method of Vautard and Ghil, Phys. D. 1989
%
% syntax : [eig_val,eig_vec,PC,RC,RCp]=SSA(X,[M, K])
%   Inputs 
%   X :  line vector
%   M : window length. Default value is M=length(X)/10.
%   K : number of EOFs used for reconstruction (0 by default)
%
% output : 
%   eig_val : eigenvalue spectrum
%   eig_vec : eigenvector matrix ("temporal EOFs")
%   PC      : matrix of principal components
%   RC      : matrix of RCs (N*M, K) (only if K>0)
%   RCp     : Reconstructed timeseries
%   
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% first make sure the vector size is 1*N
if size(X,1)~= 1
    X=X';
end
N=length(X); 
Xr=(X-mean(X)); % center the series
% set default value for M
if nargin('SSA')==0
    M=round(N/10);
    K=0;
elseif nargin('SSA')==-1
        M=varargin{1};
        K=0;
elseif nargin('SSA')==-2
        M=varargin{1};   
        K=varargin{2};
end
Np=N-M+1;
% compute autocorelation
[gam,lags]=xcorr(Xr,M-1,'unbiased');
% Fill in Covariance matrix
C=toeplitz(gam(M:2*M-1)); %take postive half of autocorrelation diagram, hence M to 2M-1
%C=toeplitz(gam(1:M)); 

% apply SVD

% solve eigenvalue problem
[V,D]=eig(C);
eig_vec=fliplr(flipud(V)); % flip them to have them ranked in decreasing order
eig_val=fliplr(flipud(D));

% compute PCs
decal=zeros(Np,M);
for t=1:N-M+1
    decal(t,:)=Xr(t:M+t-1);
end
PC=decal*eig_vec; % the columns of this matrix are Ak(t), k=1 to M


% compute reconstructed timeseries if K > 0
if (K>=1)
    RC=zeros(N,K);
     % first M terms   
     for t=1:M-1
        Av=flipud(PC(1:t,1:K));
        eig_vec_red=eig_vec(1:t,1:K);
        RC(t,:)=1/t*sum(Av.*eig_vec_red,1);    
     end
     %middle of timeseries
     for t=M:Np
        Av=flipud(PC(t-M+1:t,1:K));
        eig_vec_red=eig_vec(1:M,1:K);
        RC(t,:)=1/M*sum(Av.*eig_vec_red,1);    
     end  
     % Last M terms
     for t=Np+1:N
        Av=flipud(PC(t-M+1:Np,1:K));
        eig_vec_red=eig_vec(t-N+M:M,1:K);
        RC(t,:)=1/(N-t+1)*sum(Av.*eig_vec_red,1);  
     end  
     %sum and restore the mean
     RCp=sum(RC,2)+mean(Xr);
 else 
     RC=[];
     RCp=[];
end


