function [rotation_matrix, rotated_signal, autovals, reconstruction_matrix] = PiCA(x, peaks, peaks2, win_size, sig2, cant_delays)
%
% [y,W,A] = PiCA(x,peaks1,peaks2)
% Pseudo-Periodic Component Analysis
%
% input:
% x: input data array (channels x samples)
% peaks1: indexes of first signal peaks (R-wave locations for ECG signals)
% peaks2 (optional): indexes of second signal peaks (R-wave locations for ECG signals)
%
% outputs:
% y: pseudo-periodic components ranked in order of resemblance with the
% first to second (if available) desired signals.
% W: the decomposition matrix
% A: the mixing matrix
%
% comment: if the signal peaks2 is not available the components are ranked
% from the most similar to the least similar to the signal with
% corresponding to peaks1.
% 
% Reference:
% R. Sameni, C. Jutten, and M. B. Shamsollahi. Multichannel electrocardiogram
%  decomposition using periodic component analysis. IEEE Transactions on Biomedical Engineering,
%  55(8):1935-1940, Aug. 2008.
%
% Open Source ECG Toolbox, version 2.0, October 2008
% Released under the GNU General Public License
% Copyright (C) 2008  Reza Sameni
% Sharif University of Technology, Tehran, Iran -- LIS-INPG, Grenoble, France
% reza.sameni@gmail.com
% 
% This program is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation; either version 2 of the License, or (at your
% option) any later version.
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.
% 
% See also autovec_calculation
% 
% Adapted by Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar 
% to ecg-kit toolbox for Matlab.
% Version: 0.1 beta
% Last update: 14/5/2014
% Birthdate  : 21/4/2015
% Copyright 2008-2015
% 
if( nargin < 6 || isempty(cant_delays) )
    cant_delays = 1;
end

if( nargin < 4 )
    win_size = 100;
end

if( nargin < 3 )
    peaks2 = [];
end

[nsamp, nsig] = size(x);

if( nsamp < nsig )
    x = x';
    [nsamp, nsig] = size(x);
end

if( cant_delays < 2)
    
    % traditional PiCA
    
    A = DelayedCovMat(x, peaks, win_size, nsamp, 1);
    B = DelayedCovMat(x, peaks, win_size, nsamp, 0);

    if( isempty(peaks2) )
        [V,D] = eig(A,B,'chol');
    else
        % PM time calculation for the second peaks sequence
        if( nargin < 5 || isempty(sig2) )
            sig2 = x;
        end

    %     figure(99)

        AA = DelayedCovMat(sig2, peaks, win_size, nsamp, 1);

        [V,D] = eig(A-AA,B,'chol');
    end

    d = diag(D);
    
else
    
    % joint diagonalization of several cov matrices for cant_delays delays
    
%     CovMats = nan(4,4,cant_delays+1);
%     for ii = 0:cant_delays
%         CovMats(:,:,ii+1) = DelayedCovMat(x, peaks, win_size, nsamp, ii);
%     end    
%     
%     [V,D]=acdc(CovMats,[],[],[],[],max(max(max(CovMats)))*1e-3);
%     d = mean(D,2);
    
    CovMats = [];
    for ii = 0:cant_delays
        CovMats = [CovMats DelayedCovMat(x, peaks, win_size, nsamp, ii)];
    end    
    
    [ V ,  D ] = joint_diag_r(CovMats,1e-3);    
    
    d = diag(mean(reshape(D,4,4,cant_delays+1), 3));
    
    
end

[autovals, aux_idx] = sort(d, 'descend');
rotation_matrix = V(:,aux_idx);

if nargin > 1
    rotated_signal = x*rotation_matrix;
end

if nargin > 3
    reconstruction_matrix = pinv(rotation_matrix);
end


% function [T0, T1] = CalcSyncIndexes( peaks, win_size, nsamp )
% 
%     peaks = peaks( (peaks - win_size) > 0  & (peaks + win_size ) <= nsamp );
%     aux_seq_idx = 1:length(peaks);
%     T0 = cell2mat(arrayfun(@(a)( peaks(a) - win_size:peaks(a) + win_size ), aux_seq_idx(1:end-1), 'UniformOutput', false));
%     T1 = cell2mat(arrayfun(@(a)( peaks(a) - win_size:peaks(a) + win_size ), aux_seq_idx(2:end), 'UniformOutput', false));
% 
% %     cla
% %     hold on
% %     aux_idx = arrayfun(@(a)( peaks(a) - win_size:peaks(a) + win_size ), aux_seq_idx(1:end-1), 'UniformOutput', false);
% %     cellfun( @(a)( plot(x(a,:)) ), aux_idx )
% %     hold off



    

