% // ====================================================================
% // This file is part of the Endmember Induction Algorithms Toolbox for MATLAB 
% // Copyright (C) Grupo de Inteligencia Computacional, Universidad del 
% // País Vasco (UPV/EHU), Spain, released under the terms of the GNU 
% // General Public License.
% //
% // Endmember Induction Algorithms Toolbox 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 3 of the 
% // License, or (at your option) any later version.
% //
% // Endmember Induction Algorithms Toolbox 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.
% //
% // You should have received a copy of the GNU General Public License
% // along with Endmember Induction Algorithms Toolbox. 
% // If not, see <http://www.gnu.org/licenses/>.
% // ====================================================================

function [E,C] = EIA_3D(data,algorithm,varargin)
%% [E,C] = EIA_3D(data,algorithm,varargin)
% 
% Manuel Grana <manuel.grana[AT]ehu.es>
% Miguel Angel Veganzones <miguelangel.veganzones[AT]ehu.es>
% Grupo de Inteligencia Computacional (GIC), Universidad del Pais Vasco /
% Euskal Herriko Unibertsitatea (UPV/EHU)
% http://www.ehu.es/computationalintelligence
% 
% Copyright (2011) Grupo de Inteligencia Computacional @ Universidad del Pais Vasco, Spain.
%
% Endmembers induction algorithms for 3-spatial dimensionality data.
% 3-spatial data is defined as an hypercube where first dimension represents
% the spectral information and, second, third and fourth dimensions are the spatial ones.
% Examples of 3-spatial data are hyperspectral MRI images where
% each voxel (spatial dimensionality) is an N-dimensional feature vector (spectral
% dimensionality).
% ------------------------------------------------------------------------------
% Input:   data      : column data cube [nvariables x voxel_dim1 x voxel_dim2 x voxel_dim3]
%          algorithm : EIA to be used. It can be one of this:
%                      {'ILSIA'(default)|'EIHA'|'WM'|'NFINDR'|'FIPPI'|'ATGP'}
%          varargin  : options to be passed to the algorithm (see below).
%
% Output:  E         : set of induced endmembers [nvariables x p]
%          C         : induced endmembers indexes vector [nrows x ncolumns] with {0,1} 
%                      values, where '1' indicates that the corresponding sample
%                      has been identified as an endmember. Some of the
%                      algorithms do not select pixels as the endmembers
%                      and, in that case C is empty.
%                  
% Now, a description of the algorithms is offered together to the options
% that can be passed as parameters.
%
% * ILSIA: Incremental lattice Source Induction Algorithm (ILSIA) endmembers induction algorithm.
%   - Bibliographical references:
%       [1] M. Graña, D. Chyzhyk, M. García-Sebastián, y C. Hernández, “Lattice independent component analysis for functional magnetic resonance imaging”, Information Sciences, vol. 181, nº. 10, págs. 1910-1928, May. 2011.
%   - Options: {'alpha'}
%       'alpha': Chebyshev-best approximation tolerance threshold (>= 0). Default = 0.
%
% * EIHA: Endmember induction heuristic algorithm (EIHA) endmembers induction algorithm.
%   - Bibliographical references:
%       [1] M. Grana, I. Villaverde, J. O. Maldonado, y C. Hernandez, «Two lattice computing approaches for the unsupervised segmentation of hyperspectral images», Neurocomput., vol. 72, nº. 10-12, págs. 2111-2120, 2009.
%   - Options: {'alpha'}
%       'alpha': perturbation tolerance. Default = 2.
%
% * WM: Prof. Ritter's WM endmembers induction algorithm.
%   - Bibliographical references:
%       [1] G. X. Ritter y G. Urcid, “A lattice matrix method for hyperspectral image unmixing”, Information Sciences, vol. In Press, Corrected Proof, Oct. 2010.
%   - Options: none.
%
% * NFINDR: N-FINDR endmembers induction algorithm.
%   - Bibliographical references:
%       [1] Winter, M. E., «N-FINDR: an algorithm for fast autonomous spectral end-member determination in hyperspectral data», presented at the Imaging Spectrometry V, Denver, CO, USA, 1999, vol. 3753, págs. 266-275.
%   - Options: {'p'|'maxit'}
%       'p': number of endmembers to be induced. If not provided it is calculated by HFC method with tol=10^(-5).
%       'maxit': maximum number of iterations. Default = 3*p.
%
% * FIPPI: Fast Iterative Pixel Purity Index (FIPPI) endmembers induction algorithm.
%   - Bibliographical references:
%       [1] Chang, C.-I., “A fast iterative algorithm for implementation of pixel purity index”, Geoscience and Remote Sensing Letters, IEEE, vol. 3, nº. 1, págs. 63-67, 2006.
%   - Options: {'alpha'}
%       'p': number of endmembers to be induced. If not provided it is calculated by HFC method with tol=10^(-5).
%       'maxit': maximum number of iterations. Default = 3*p.
%
% * ATGP: ATGP endmembers induction algorithm.
%   - Bibliographical references:
%       [1] A. Plaza y C.-I. Chang, “Impact of Initialization on Design of Endmember Extraction Algorithms”, Geoscience and Remote Sensing, IEEE Transactions on, vol. 44, nº. 11, págs. 3397-3407, 2006.
%   - Options: {'p'}
%       'p': number of endmembers to be induced. If not provided it is calculated by HFC method with tol=10^(-5).
%

%% check parameters
if nargin < 1
    error('Not enough parameters');
end
if nargin < 2
    algorithm = 'ILSIA';
end

%% Reshape data
[p m n o] = size(data);
data = reshape(data,p,m*n*o);

%% Algorithms
switch lower(algorithm)
    case {'eiha'}
        disp('EIHA algorithm');
        optargin = size(varargin,2);
        if optargin > 0
            alpha = [];
            for i=1:2:optargin
                if strcmpi(varargin{i},'alpha')
                    alpha = varargin{i+1};
                    break;
                end
            end
            [E,C] = EIA_EIHA(data,alpha);
        else
            [E,C] = EIA_EIHA(data);
        end
    case {'wm'}
        disp('WM algorithm');
        [E] = EIA_WM(data);
        C = [];
    case {'nfindr'}
        disp('N-FINDR algorithm');
        optargin = size(varargin,2);
        if optargin > 0
            p = []; maxit = [];
            for i=1:2:optargin
                if strcmpi(varargin{i},'p')
                    p = varargin{i+1};
                elseif strcmpi(varargin{i},'maxit')
                    maxit = varargin{i+1};
                end
            end
            [E,C] = EIA_NFINDR(data,p,maxit);
        else
            [E,C] = EIA_NFINDR(data);
        end
    case {'fippi'}
        disp('FIPPI algorithm');
        optargin = size(varargin,2);
        if optargin > 0
            p = []; maxit = [];
            for i=1:2:optargin
                if strcmpi(varargin{i},'p')
                    p = varargin{i+1};
                elseif strcmpi(varargin{i},'maxit')
                    maxit = varargin{i+1};
                end
            end
            [E,C] = EIA_FIPPI(data,p,maxit);
        else
            [E,C] = EIA_FIPPI(data);
        end
    case {'atgp'}
        disp('ATGP algorithm');
        optargin = size(varargin,2);
        if optargin > 0
            p = []; maxit = [];
            for i=1:2:optargin
                if strcmpi(varargin{i},'p')
                    p = varargin{i+1};
                elseif strcmpi(varargin{i},'maxit')
                    maxit = varargin{i+1};
                end
            end
            [E,C] = EIA_ATGP(data,p,maxit);
        else
            [E,C] = EIA_ATGP(data);
        end
    otherwise % ILSIA
        disp('ILSIA algorithm');
        optargin = size(varargin,2);
        if optargin > 0
            alpha = [];
            for i=1:2:optargin
                if strcmpi(varargin{i},'alpha')
                    alpha = varargin{i+1};
                    break;
                end
            end
            [E,C] = EIA_ILSIA(data,alpha);
        else
            [E,C] = EIA_ILSIA(data);
        end
end

%% Reshape C
if size(C) > 0
    C = reshape(c,p,m,n,o);
end