
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%  Title: StatisCLAS: A Package of Classification Methods   %%%%
%%%%  Author: David Casado de Lucas                            %%%%
%%%%  Version: 29th May 2013                                   %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% PURPOSE: This function implements the robust functional classification.

% INPUT VARIABLES:
%    groupFD1: Matrix with the training curves of group 1 as rows.
%    groupFD1test: Matrix with the testing curves of group 1 as rows.
%    groupFD2: Matrix with the training curves of group 2 as rows.
%    groupFD2test: Matrix with the testing curves of group 2 as rows.
%    contamination: Optional logical variable to indicate the presence of contamination.
%    alpha: Parameter to determine the trim when contamination = true.
%    numberFDdistance: Number of the distance between functions to be applied (see 'distancesFD.m').

% OUTPUT VARIABLES:
%    errorRatesGroup1: Number of misclassified testing elements of group 1 (out of m1).
%    errorRatesGroup2: Number of misclassified testing elements of group 2 (out of m2).
%    referenceGroupFD1: Reference function of the training elements of group 1.
%    referenceGroupFD1alpha: Trimmed reference function of the training elements of group 1.
%                       It is identical to 'referenceGroupFD1' when contamination = false.
%    referenceGroupFD2: Reference function of the training elements of group 2.
%    referenceGroupFD2alpha: Trimmed reference function of the training elements of group 1.
%                       It is identical to 'referenceGroupFD2' when contamination = false.
%    groupMV1: Matrix with the univariate variable (difference of the distances to the
%              two representative functions of the groups) for the training sample 1,
%              using the training reference functions (first column) and the training
%              trimmed reference functions (second column).
%    groupMV1test: Matrix with the univariate variable (difference of the distances to the
%                  two representative functions of the groups) for the testing sample 1,
%                  using the training reference functions (first column) and the training
%                  trimmed reference functions (second column).
%    groupMV2: Matrix with the univariate variable (difference of the distances to the
%              two representative functions of the groups) for the training sample 2,
%              using the training reference functions (first column) and the training
%              trimmed reference functions (second column).
%    groupMV2test: Matrix with the univariate variable (difference of the distances to the
%                  two representative functions of the groups) for the testing sample 2,
%                  using the training reference functions (first column) and the training
%                  trimmed reference functions (second column).

% COMMENTS:
%   (1) In our code, this function is called in two different ways: to get only the error
%       rates and to get additional output information.
%   (2) This function and its subordinated ones can be used with any functional data,
%       outside the framework of this paper.
%   (3) This function applies a trim to calculate the curve at which 'numberFDreference',
%       points, so 'numberFDreference' must be different to 2.
%   (4) This function is based on code of Sara López-Pintado.

function [errorRatesGroup1 errorRatesGroup2...
          referenceGroupFD1 referenceGroupFD1alpha referenceGroupFD2 referenceGroupFD2alpha...
          groupMV1 groupMV1test groupMV2 groupMV2test] =...
    functionRFC(groupFD1, groupFD1test, groupFD2, groupFD2test, contamination, alpha,...
    numberFDdistance, numberFDreference, infoFDreference)

if ~exist('alpha','var') || isempty(alpha)
  alpha = 0.2;
end
if ~exist('numberFDdistance','var')
  numberFDdistance = 1;  % The L1 distance
end
if ~exist('numberFDreference','var')
  numberFDreference = 1;  % The mean
end
if isequal(numberFDreference,2) % When called with the trimmed mean...
  numberFDreference = 1; % ...the mean is enabled instead, not to trim twice
end
if ~exist('infoFDreference','var')
  infoFDreference = {};
end

% To record the misclassification error rates. When DbC-alpha is disabled,
% (contamination = false) the second position is not used
errorRatesGroup1 = zeros(1,2);
errorRatesGroup2 = zeros(1,2);

% Sizes of the training samples
n1 = size(groupFD1,1);
n2 = size(groupFD2,1);
% Sizes of the testing samples (possible 0, if the matrix is empty)
m1 = size(groupFD1test,1);
m2 = size(groupFD2test,1);

% Reference curves of the training samples
referenceGroupFD1 = referenceElement(numberFDreference,infoFDreference,groupFD1);
referenceGroupFD2 = referenceElement(numberFDreference,infoFDreference,groupFD2);

if exist('contamination','var') && contamination
  % Computing the depth and the trimmed reference curves of the training samples
  referenceGroupFD1alpha = trimFunction(groupFD1,alpha,numberFDreference,infoFDreference);
  referenceGroupFD2alpha = trimFunction(groupFD2,alpha,numberFDreference,infoFDreference);
else
  referenceGroupFD1alpha = referenceGroupFD1;
  referenceGroupFD2alpha = referenceGroupFD2;
end

% To store the univariate variable measuring the difference between the
% distances from the testing curves to the training reference curves
groupsMVtest = zeros(m1+m2,2);
% Computing the misclassification error rates
if isempty(groupFD1test)
  errorRatesGroup1 = zeros(1,2);
else
  % For the test sample 1 and the references
  groupsMVtest(1:m1,1) = distancesFD(numberFDdistance,groupFD1test,referenceGroupFD1) - distancesFD(numberFDdistance,groupFD1test,referenceGroupFD2);
  errorRatesGroup1(1) = sum(groupsMVtest(1:m1,1) > 0) + errorRatesGroup1(1);
  if exist('contamination','var') && contamination
    % For the test sample 1 and the trimmed references
    groupsMVtest(1:m1,2) = distancesFD(numberFDdistance,groupFD1test,referenceGroupFD1alpha) - distancesFD(numberFDdistance,groupFD1test,referenceGroupFD2alpha);
    errorRatesGroup1(2) = sum(groupsMVtest(1:m1,2) > 0) + errorRatesGroup1(2);
  end
end
if isempty(groupFD2test)
  errorRatesGroup2 = zeros(1,2);
else
  % For the test sample 2 and the references
  groupsMVtest((m1+1):(m1+m2),1) = distancesFD(numberFDdistance,groupFD2test,referenceGroupFD1) - distancesFD(numberFDdistance,groupFD2test,referenceGroupFD2);
  errorRatesGroup2(1) = sum(groupsMVtest((m1+1):(m1+m2),1) < 0) + errorRatesGroup2(1);
  if exist('contamination','var') && contamination
    % For the test sample 2 and the trimmed references
    groupsMVtest((m1+1):(m1+m2),2) = distancesFD(numberFDdistance,groupFD2test,referenceGroupFD1alpha) - distancesFD(numberFDdistance,groupFD2test,referenceGroupFD2alpha);
    errorRatesGroup2(2) = sum(groupsMVtest((m1+1):(m1+m2),2) < 0) + errorRatesGroup2(2);
  end
end

% To store the univariate variable measuring the difference between the
% distances from the training curves to the training reference curves
groupsMV = zeros(n1+n2,2);
% For the training sample 1 and the references
groupsMV(1:n1,1) = distancesFD(numberFDdistance,groupFD1,referenceGroupFD1) - distancesFD(numberFDdistance,groupFD1,referenceGroupFD2);
% For the training sample 2 and the references
groupsMV((n1+1):(n1+n2),1) = distancesFD(numberFDdistance,groupFD2,referenceGroupFD1) - distancesFD(numberFDdistance,groupFD2,referenceGroupFD2);
if exist('contamination','var') && contamination
  % For the training sample 1 and the trimmed references
  groupsMV(1:n1,2) = distancesFD(numberFDdistance,groupFD1,referenceGroupFD1alpha) - distancesFD(numberFDdistance,groupFD1,referenceGroupFD2alpha);
  % For the training sample 2 and the trimmed references
  groupsMV((n1+1):(n1+n2),2) = distancesFD(numberFDdistance,groupFD2,referenceGroupFD1alpha) - distancesFD(numberFDdistance,groupFD2,referenceGroupFD2alpha);
end

groupMV1 = groupsMV(1:n1,:);
groupMV1test = groupsMVtest(1:m1,:);
groupMV2 = groupsMV((n1+1):(n1+n2),:);
groupMV2test = groupsMVtest((m1+1):(m1+m2),:);

end
