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

% PURPOSE: This function calculates a curve from each time series, by applying a
%                 transformation to the blocks into which series are split.

% INPUT VARIABLES:
%    numberTStoFDmethod: Number of the transformation to be applied.
%    series: Matrix with the series as rows.
%    numberBlocks: When it is given, number of blocks into which series are split.

% OUTPUT VARIABLES:
%    functions: Matrix of size sampleSize by T with the generated curve (by merging the
%       curve of each blocks).

% COMMENTS:
%   (2) This function can be used outside the framework of this paper.

function functions = fromTStoFD(numberTStoFDmethod, infoTStoFDmethod, series)

% Trick for the case leaveOneOut = true
if isempty(series)
  functions = [];
  return
end

numberBlocks = infoTStoFDmethod{1};

switch numberTStoFDmethod
  case 0  % Identity: trick for direct time series classification methods
      functions = series;
  case 1  % Normalized integrated periodogram
    if isequal(numberBlocks,1)
      functions = toPeriodogram(series);
      functions = toIntegration(functions);
      functions = toNormalization(functions);
    else
      sampleSize = size(series,1);
      lenBlock = floor(size(series,2)/numberBlocks);
      blo = periodogram(series(1, 1:lenBlock));
      len1 = length(blo);
      len2 = length(toIntegration(blo));
      functions = zeros(sampleSize, numberBlocks*len2);
      perMatrix = zeros(sampleSize, numberBlocks*len1);
      for i1 = 0:(numberBlocks-1)            
        perMatrix(:, (i1*len1 + 1):((i1 + 1)*len1)) =...
            toPeriodogram(series(:, (i1*lenBlock + 1):((i1 + 1)*lenBlock)));
        functions(:, (i1*len2 + 1):((i1 + 1)*len2)) =...
            toIntegration(perMatrix(:, (i1*len1 + 1):((i1 + 1)*len1)));
        functions(:, (i1*len2 + 1):((i1 + 1)*len2)) =...
            toNormalization(functions(:, (i1*len2 + 1):((i1 + 1)*len2)));
      end
    end
  case 2  % Nonnormalized integrated periodogram
    if isequal(numberBlocks,1)
      functions = toPeriodogram(series);
      functions = toIntegration(functions);
    else
      sampleSize = size(series,1);
      lenBlock = floor(size(series,2)/numberBlocks);
      blo = periodogram(series(1, 1:lenBlock));
      len1 = length(blo);
      len2 = length(toIntegration(blo));
      functions = zeros(sampleSize, numberBlocks*len2);
      perMatrix = zeros(sampleSize, numberBlocks*len1);
      for i1 = 0:(numberBlocks-1)            
        perMatrix(:, (i1*len1 + 1):((i1 + 1)*len1)) =...
            toPeriodogram(series(:, (i1*lenBlock + 1):((i1 + 1)*lenBlock)));
        functions(:, (i1*len2 + 1):((i1 + 1)*len2)) =...
            toIntegration(perMatrix(:, (i1*len1 + 1):((i1 + 1)*len1)));
      end
    end
  case 3  % Periodogram
    if isequal(numberBlocks,1)
      functions = toPeriodogram(series);
    else
      sampleSize = size(series,1);
      lenBlock = floor(size(series,2)/numberBlocks);
      len1 = length(periodogram(series(1, 1:lenBlock)));
      functions = zeros(sampleSize, numberBlocks*len1);
      for i1 = 0:(numberBlocks-1)
        functions(:, (i1*len1 + 1):((i1 + 1)*len1)) =...
            toPeriodogram(series(:, (i1*lenBlock + 1):((i1 + 1)*lenBlock)));
      end
    end
  case 4  % Logarithm of the periodogram
    if isequal(numberBlocks,1)
      functions = toPeriodogram(series);
      functions = log(functions);
    else
      sampleSize = size(series,1);
      lenBlock = floor(size(series,2)/numberBlocks);
      len1 = length(periodogram(series(1, 1:lenBlock)));
      functions = zeros(sampleSize, numberBlocks*len1);
      for i1 = 0:(numberBlocks-1)
        functions(:, (i1*len1 + 1):((i1 + 1)*len1)) =...
            toPeriodogram(series(:, (i1*lenBlock + 1):((i1 + 1)*lenBlock)));
        functions(:, (i1*len1 + 1):((i1 + 1)*len1)) =...
            log(functions(:, (i1*len1 + 1):((i1 + 1)*len1)));
      end
    end
end

end


% PURPOSE: This function calculate the periodogram of time series.
% INPUT VARIABLES:
%    series: Matrix with the time series as rows.
% OUTPUT VARIABLES:
%    curves: Matrix with the periodograms as rows.
function curves = toPeriodogram(series)
  n = size(series,1);
  curves = periodogram(series(1,:))';
  len = length(curves);
  curves = [curves; zeros(n-1,len)];
  for i1 = 2:n
    curves(i1,:) = periodogram(series(i1,:));
  end
end

% PURPOSE: This function integrates functions and normalizes the result.
% INPUT VARIABLES:
%    curves: Matrix with the functions as rows.
% OUTPUT VARIABLES:
%    intCurves: Matrix with the integrated functions as rows.
function intCurves = toIntegration(curves)
  % intCurves = cumsum(curves,2)/(size(curves,2)-1);  % 1/(size(curves,2)-1) is the step 
  intCurves = cumsum(curves,2);  % To avoid calculations...
end

% PURPOSE: This function divides by the last value, that is also the maximum
%          for increasing functions (so the integrated periodogram is).
% INPUT VARIABLES:
%    curves: Matrix with the functions as rows.
% OUTPUT VARIABLES:
%    intCurves: Matrix with the integrated functions as rows.
function norCurves = toNormalization(curves)
  norCurves = curves./nncopy(curves(:,end),1,size(curves,2));
end
