% STD_TOPOPLOT - Command line function to plot cluster component and mean scalp maps. 
%                  Displays either mean cluster/s scalp map/s, or all cluster/s components
%                  scalp maps with the mean cluster/s scsalp map in one figure.
%                  The scalp maps can be visualized only if component scalp maps     
%                  were calculated and saved in the EEG datasets in the STUDY.
%                  These can be computed during pre-clustering using the GUI-based function
%                  POP_PRECLUST or the equivalent commandline functions EEG_CREATEDATA 
%                  and EEG_PRECLUST. A pop-function that calls this function is 
%                  POP_CLUSTEDIT.
% Usage:    
%              >> [STUDY] = std_topoplot(STUDY, ALLEEG, key1, val1, key2, val2);  
% Inputs:
%   STUDY      - EEGLAB STUDY set comprising some or all of the EEG datasets in ALLEEG.
%   ALLEEG     - global EEGLAB vector of EEG structures for the dataset(s) included in 
%                the STUDY. ALLEEG for a STUDY set is typically created using LOAD_ALLEEG.
% Optional inputs:
%   'clusters'   - [numeric vector| 'all']  -> specific cluster numbers to plot.
%                  'all' -> plot all clusters in STUDY.
%                  {default: 'all'}.
%   'comps'      - [numeric vector | 'all']  -> indices of the cluster components to plot.
%                  'all' -> plot all the components in the cluster 
%                  {default: 'all'}.
%   'mode'       - ['together'|'apart'] a plotting mode. In 'together' mode, the average 
%                  scalp maps of the requested clusters are plotted in the same figure,
%                  one per condition.  In 'apart' mode, component scalp maps for each 
%                  cluster are plotted in a separate figure for each condition, plus the 
%                  cluster mean map. Note that this option is irrelevant if component 
%                  indices ('comps' above) are provided.{default: 'apart'}. 
%   'figure'     - ['on'|'off'] for the 'together' mode option, plots on
%                  a new figure ('on'),  or on the current figure ('off').
%                  {default: 'on'}.
% Outputs:
%   STUDY        - the input STUDY set structure modified with plotted cluster scalp
%                  map means, to allow quick replotting (unless clusters meands 
%                  already exists in th STUDY).  
%
%   Example:
%              % Plot the mean scalp maps for clusters 1 through 20 on the same figure. 
%           >> [STUDY] = std_topoplot(STUDY,ALLEEG, 'clusters', [1:20], 'mode', 'together');
%
%  See also  POP_CLUSTEDIT, POP_PRECLUST
%
% Authors:  Hilit Serby, Arnaud Delorme, Scott Makeig, SCCN, INC, UCSD, June, 2005

% Copyright (C) Hilit Serby, SCCN, INC, UCSD, June 07, 2005, hilit@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function STUDY = std_topoplot(STUDY, ALLEEG,  varargin)
icadefs;

% Set default values
cls = [];
mode = 'together'; % plot all cluster mean scalp maps on one figure
figureon = 1; % plot on a new figure

for k = 3:2:nargin
    switch varargin{k-2}
        case 'clusters'
            if isnumeric(varargin{k-1})
                cls = varargin{k-1};
                if isempty(cls)
                    cls = 2:length(STUDY.cluster);
                end
            else
                if ischar(varargin{k-1}) && strcmpi(varargin{k-1}, 'all')
                    cls = 2:length(STUDY.cluster);
                else
                    error('std_topoplot: ''clusters'' input takes either specific clusters (numeric vector) or keyword ''all''.');
                end
            end
        case 'plotsubjects' % legacy
            mode = 'apart';
        case 'comps'
            if ischar( varargin{k-1} ), mode = 'apart'; 
            else STUDY = std_plotcompmap(STUDY, ALLEEG,  cls, varargin{k-1}); return;
            end
        case 'mode' % Plotting mode 'together' / 'apart'
            mode = varargin{k-1};
        case 'figure'
            if strcmpi(varargin{k-1},'off')
                figureon = 0;
            end
        case 'plotrad'
            inputPlotrad = varargin{k-1};
    end
end
        
% select clusters to plot
% -----------------------
if isempty(cls)
    tmp =[];
    cls = 2:length(STUDY.cluster); % plot all clusters in STUDY
    for k = 1: length(cls)
        % don't include 'Notclust' clusters
        if ~strncmpi('Notclust',STUDY.cluster(cls(k)).name,8) && ~strncmpi('ParentCluster',STUDY.cluster(cls(k)).name,13)
            tmp = [tmp cls(k)];
        end
    end
    cls = tmp;
end

% Plot all the components in the cluster
disp('Drawing components of cluster (all at once)...');
if ~isfield(STUDY.cluster,'topo'), STUDY.cluster(1).topo = []; end
for clus = 1: length(cls) % For each cluster requested
    if isempty(STUDY.cluster(cls(clus)).topo)
        STUDY = std_readtopoclust(STUDY,ALLEEG, cls(clus));
    end
end
if strcmpi(mode, 'apart')         
    for clus = 1: length(cls) % For each cluster requested
        len = length(STUDY.cluster(cls(clus)).comps);
        if len > 0 % A non-empty cluster 
            h_topo = figure;
            rowcols(2) = ceil(sqrt(len + 4)); rowcols(1) = ceil((len+4)/rowcols(2));
            clusscalp = STUDY.cluster(cls(clus));
            ave_grid = clusscalp.topo;
            tmp_ave = ave_grid;
            tmp_ave(find(isnan(tmp_ave))) = 0; % remove NaN values from grid for later correlation calculation.  
            for k = 1:len
                abset   = STUDY.datasetinfo(STUDY.cluster(cls(clus)).sets(1,k)).index;
                subject = STUDY.datasetinfo(STUDY.cluster(cls(clus)).sets(1,k)).subject;
                comp = STUDY.cluster(cls(clus)).comps(k);
                [Xi,Yi] = meshgrid(clusscalp.topoy,clusscalp.topox);                     
                scalpmap = squeeze(clusscalp.topoall{k}); % already correct polarity
                if k <= rowcols(2) - 2 %first sbplot row
                    sbplot(rowcols(1),rowcols(2),k+2) , 
                    toporeplot(scalpmap, 'style', 'both', 'plotrad',0.5,'intrad',0.5, 'verbose', 'off','xsurface', Xi, 'ysurface', Yi );
                    title([subject '/' 'IC' num2str(comp)   ], 'interpreter', 'none');
                    colormap(DEFAULT_COLORMAP);
                else %other sbplot rows
                    sbplot(rowcols(1),rowcols(2),k+4) , 
                    toporeplot(scalpmap, 'style', 'both', 'plotrad',0.5,'intrad',0.5, 'verbose', 'off','xsurface', Xi, 'ysurface', Yi );
                    title([subject '/' 'IC' num2str(comp)], 'interpreter', 'none');
                    colormap(DEFAULT_COLORMAP);
                end
            end
            sbplot(rowcols(1),rowcols(2),[1 rowcols(2)+2 ]) ,
            toporeplot(ave_grid, 'style', 'both', 'plotrad',0.5,'intrad',0.5, 'verbose', 'off');
            title([ STUDY.cluster(cls(clus)).name ' (' num2str(length(unique(STUDY.cluster(cls(clus)).sets(1,:)))) ' Ss, ' num2str(length(STUDY.cluster(cls(clus)).comps)),' ICs)']);
            set(gcf,'Color', BACKCOLOR);
            colormap(DEFAULT_COLORMAP);
            orient tall  % fill the figure page for printing
            axcopy
        end % Finished one cluster plot 
    end   % Finished plotting all clusters
end % Finished 'apart' plotting mode

% Plot clusters centroid maps
if strcmpi(mode, 'together') 
    len = length(cls);
    rowcols(2) = ceil(sqrt(len)); rowcols(1) = ceil((len)/rowcols(2));
    if figureon
        figure   
    end
    for k = 1:len 
       if len ~= 1
            sbplot(rowcols(1),rowcols(2),k)  
       end
        tmpcmap = colormap(DEFAULT_COLORMAP);
        toporeplot(STUDY.cluster(cls(k)).topo, 'style', 'both', 'plotrad',0.5,'intrad',0.5, 'verbose', 'off','colormap', tmpcmap);
        title([ STUDY.cluster(cls(k)).name ' (' num2str(length(unique(STUDY.cluster(cls(k)).sets(1,:)))) ' Ss, ' num2str(length(STUDY.cluster(cls(k)).comps)),' ICs)']);
        colormap(DEFAULT_COLORMAP);
        %title([ STUDY.cluster(cls(k)).name ', ' num2str(length(unique(STUDY.cluster(cls(k)).sets(1,:)))) 'Ss' ]);
    end
    if len ~= 1
        maintitle = 'Average scalp map for all clusters';
        a = textsc(maintitle, 'title'); 
        set(a, 'fontweight', 'bold');
        set(gcf,'name', maintitle);
    else
        title([ STUDY.cluster(cls(k)).name ' (' num2str(length(unique(STUDY.cluster(cls(k)).sets(1,:)))) ' Ss, ' num2str(length(STUDY.cluster(cls(k)).comps)),' ICs)']);
        set(gcf,'name',['Scalp map of ' STUDY.cluster(cls(k)).name ' (' num2str(length(unique(STUDY.cluster(cls(k)).sets(1,:)))) ' Ss, ' num2str(length(STUDY.cluster(cls(k)).comps)),' ICs)']);
        %title([ STUDY.cluster(cls(k)).name ' scalp map, ' num2str(length(unique(STUDY.cluster(cls(k)).sets(1,:)))) 'Ss' ]);
    end
    set(gcf,'Color', BACKCOLOR);

    orient tall
    axcopy
end        

% STD_PLOTCOMPMAP - Commandline function, to visualizing cluster components scalp maps. 
%                   Displays the scalp maps of specified cluster components on separate figures. 
%                   The scalp maps can be visualized only if component scalp maps     
%                   were calculated and saved in the EEG datasets in the STUDY.
%                   These can be computed during pre-clustering using the GUI-based function
%                   POP_PRECLUST or the equivalent commandline functions EEG_CREATEDATA 
%                   and EEG_PRECLUST. A pop-function that calls this function is POP_CLUSTEDIT.
% Usage:    
%                   >> [STUDY] = std_plotcompmap(STUDY, ALLEEG, cluster, comps);  
% Inputs:
%   STUDY      - EEGLAB STUDY set comprising some or all of the EEG datasets in ALLEEG.
%   ALLEEG     - global EEGLAB vector of EEG structures for the dataset(s) included in the STUDY. 
%                     ALLEEG for a STUDY set is typically created using LOAD_ALLEEG.  
%   cluster     - single cluster number.  
%
% Optional inputs:
%   comps      - [numeric vector]  -> indices of the cluster components to plot.
%                       'all'                       -> plot all the components in the cluster
%                                                      (as in std_topoplot). {default: 'all'}.
%
% Outputs:
%   STUDY    - the input STUDY set structure modified with plotted cluster scalp
%                     map mean, to allow quick replotting (unless cluster mean 
%                     already existed in the STUDY).  
%
%   Example:
%                         >> cluster = 4; comps= [1 7 10];  
%                         >> [STUDY] = std_plotcompmap(STUDY,ALLEEG, cluster, comps);
%                    Plots components 1, 7 & 10  scalp maps of cluster 4 on separate figures. 
%
%  See also  pop_clustedit, pop_preclust, eeg_createdata, std_topoplot         
%
% Authors:  Hilit Serby, Arnaud Delorme, Scott Makeig, SCCN, INC, UCSD, June, 2005

% Copyright (C) Hilit Serby, SCCN, INC, UCSD, June 07, 2005, hilit@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function STUDY = std_plotcompmap(STUDY, ALLEEG, cls, varargin)
icadefs;

if ~exist('cls')
    error('std_plotcompmap: you must provide a cluster numberas an input.');
end
if isempty(cls)
   error('std_plotcompmap: you must provide a cluster numberas an input.');
end
if nargin == 3 % no component indices were given
    % Default: plot all components of the cluster
    [STUDY] = std_topoplot(STUDY, ALLEEG, 'clusters', cls, 'mode', 'apart');
    return
else
    comp_ind = varargin{1}; 
end
STUDY = std_readtopoclust(STUDY,ALLEEG, cls);
for ci = 1:length(comp_ind)
    abset = STUDY.datasetinfo(STUDY.cluster(cls).sets(1,comp_ind(ci))).index;
    subject = STUDY.datasetinfo(STUDY.cluster(cls).sets(1,comp_ind(ci))).subject;
    comp  = STUDY.cluster(cls).comps(comp_ind(ci));
    grid  = STUDY.cluster(cls).topoall{comp_ind(ci)};
    xi    = STUDY.cluster(cls).topox;
    yi    = STUDY.cluster(cls).topoy;
    [Xi,Yi] = meshgrid(yi,xi);
    figure;
    toporeplot(grid, 'style', 'both', 'plotrad',0.5,'intrad',0.5,'xsurface', Xi, 'ysurface', Yi, 'verbose', 'off');
    title([subject ' / ' 'IC' num2str(comp) ', ' STUDY.cluster(cls).name ]);
    set(gcf,'Color', BACKCOLOR);
    colormap(DEFAULT_COLORMAP);
    axcopy;
end

