function [cvv] = CrossValidation(x_val,x_cal,y_val,y_cal,LV,fold,n_class)
%   Function to perfome the cross-validation procedure including classical
%   leave-one-out, k-fold, contiguous block, and Monte Carlo cross-validation.
%   -------------------------------INPUT--------------------------------------
%   
%   x_val   - matrix {m,n}, validation matrix for each fold
%   y_val   - matrix {m,n}, classes for validation matrix in each fold
%   x_cal   - matrix {m,n}, calibration matrix for each fold
%   y_cal   - matrix {m,n}, classes for calibration matrix in each fold
%   LV      - number of LV (Latent Variables) to be tested
%   fold    - number of folds constructed for the CV
%   n_class - number of classes in X
%   -------------------------------OUTPUT-------------------------------------
%   cvv         Structure containg the data obtained after CrossValidation with
%               the follwing elements:
%               RMSECV: vector (1,h), Root Mean Square Error of Cross-Validation
%               res: 
%               res_class: 
%               LV_calibration: 
%               LV_validation: 
%               y_LV_calibration: 
%               y_LV_validation: 
%               res_class: 
%               res_all: 
%   --------------------------------------------------------------------------
%   Example:
%   [cvv]=CrossValidation(x_val,x_cal,y_val,y_cal,10,10,3)
%   --------------------------------------------------------------------------
%   References
%   [1] K. Baumann, H. Albert, M. von Korff, A systematic evaluation of the 
%   benefits and hazards of variable selection in latent variable regression. 
%   Part II. Practical applications, Journal of Chemometrics 16 (2002) 351-360
%   [2] Q.-S. Xu, Y.-Z. Liang, Monte Carlo cross validation, Chemometrics and
%   Intelligent Laboratory Systems 56 (2001) 1-11
%   [3] Jong, S., "SIMPLS: an alternative approach to Partial Least 
%   Squares Regression", Chemometrics and Intelligent Laboratory Systems 18 (1993) 251-263.
%   -----------------------------------------------------------------------------
% 
%   See also: dosy_mn, score_mn, decra_mn, mcr_mn, varianimport, 
%             brukerimport, jeolimport, peakpick_mn, dosyplot_mn, 
%             dosyresidual, dosyplot_gui, scoreplot_mn, decraplot_mn,
%             mcrplot_mn
%
%   You should have received a copy of the GNU General Public License along
%   with this program; if not, write to the Free Software Foundation, Inc.,
%   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%
%   Dr. Mathias Nilsson
%   School of Chemistry, University of Manchester,
%   Oxford Road, Manchester M13 9PL, UK
%   Telephone: +44 (0) 161 306 4465
%   Fax: +44 (0)161 275 4598
%
%   Hugo da Silva Rocha, PhD Student
%   School of Chemistry, University of Manchester,
%   Oxford Road, Manchester M13 9PL, UK
%   email: hugo.rocha@postgrad.manchester.ac.uk

%% Changes

% Checking size of matrix
[m,~]=size(x_cal);                      
cvv.res=zeros(1,LV);
cvv.res_class = zeros(LV,n_class);

h=waitbar(0,'Building the PLS-DA cross validation model');
for n=1:LV 
   h=waitbar(n/LV);
   for i=1:fold      
       [yprev_cal_cruzada,Bcal,Cc,Rc,zz,zz2] = My_pls(x_cal{i},y_cal{i},x_cal{i},0,n);
       [yprev_val_cruzada,Bval] = My_pls(x_cal{i},y_cal{i},x_val{i},0,n);
       cvv.Bcal(:,:,i,n) = Bcal;
       cvv.LV_calibration{:,:,i,n} = yprev_cal_cruzada; 
       assignin('base','LV_calibration',yprev_cal_cruzada)
       cvv.LV_validation{:,:,i,n} = yprev_val_cruzada; 
       assignin('base','LV_valibration',yprev_val_cruzada)
       cvv.y_LV_calibration{:,:,i,n} = y_cal{i};
       assignin('base','y_LV_calibration',y_cal)
       cvv.y_LV_validation{:,:,i,n} = y_val{i}; 
       assignin('base','y_LV_validation',y_val)
       cvv.res_class(n,:)=sum((cvv.y_LV_validation{:,:,i,n}-cvv.LV_validation{:,:,i,n}).^2)+cvv.res_class(n,:);
       cvv.res_all(i,n)=sum(sum((cvv.y_LV_validation{:,:,i,n}-cvv.LV_validation{:,:,i,n}).^2));
   end
end
close(h)

cvv.Cc = Cc;
cvv.Rc = Rc;
cvv.zz = zz;
cvv.zz2 = zz2;
cvv.res_c = sum(cvv.res_class,2);
cvv.res = sum(cvv.res_all);
cvv.RMSECVc=sqrt((cvv.res_class/m));
cvv.RMSECV=sqrt((cvv.res/m));

% PLS-DA thresehold calculation
for n=1:fold % number of fold
    for i=1:LV  % number of factors 
        for ko=1:n_class % number of classes
             plsda_thres=plsdafindthr(cvv.LV_calibration{:,:,n,i}(:,ko),cvv.y_LV_calibration{:,:,n,i}(:,ko));             
             b = plsda_thres;
             ts(i,ko,n)=[plsda_thres.class_thr];
             cv1=cvv.LV_validation{:,:,n,i};
             cv=cv1>=ts(i,ko,n);
             cv=double(cv);
             aw1=cv==y_val{n};
             aw=sum(aw1);
             n_correc_class_val_cruzada(i,ko,n)=sum(aw);
        end
    end
end

cvv.b=b;
cvv.ts=ts;
cvv.perc_correc_class_val_cruzada=100*(n_correc_class_val_cruzada/(n_class*size(y_val{1,1},1)));        
for ll=1:LV
    for u=1:n_class
        cvv.porc_am_class_cor(ll,u)=mean(cvv.perc_correc_class_val_cruzada(ll,u,:));
    end        
end

assignin('base','cvv',cvv)

end