% STD_ERPPLOT - Command line function to plot STUDY cluster component ERPs. Either 
%                 displays grand mean ERPs for all requested clusters in the same figure, 
%                 with ERPs for different conditions (if any) plotted in different colors. 
%                 Else, displays ERP for each specified cluster in separate figures 
%                 (per condition), each containing the cluster component ERPs plus 
%                 the grand mean cluster ERP (in bold). ERPs can be plotted only if 
%                 component ERPs were computed and saved in the STUDY EEG
%                 datasets. 
%                 These can be computed during pre-clustering using the gui-based 
%                 function POP_PRECLUST or the equivalent command line functions 
%                 EEG_CREATEDATA and EEG_PRECLUST. Called by POP_CLUSTEDIT.
%                 and STD_PROPPLOT.
% Usage:    
%   >> [STUDY] = std_erpplot(STUDY, ALLEEG, key1, val1, key2, val2);  
%   >> [STUDY erpdata erptimes pgroup pcond pinter] = std_erpplot(STUDY, ALLEEG, ...);  
%
% Inputs:
%   STUDY      - EEGLAB STUDY set comprising some or all of the EEG datasets in ALLEEG.
%   ALLEEG     - global EEGLAB vector of EEG structures for the datasets included 
%                in the STUDY. A STUDY set ALLEEG is typically created by LOAD_ALLEEG.  
% Optional inputs for channel plotting:
%   'channels' - [numeric vector]  specific channel group to plot. By
%                default, the grand mean channel ERP is plotted (using the 
%                same format as for the cluster component means described
%                above). Default is to plot all channels.
%   'subject'  - [numeric vector]  In 'changrp' mode (above), index of 
%                the subject(s) to plot. Else by default, plot all components 
%                in the cluster.
%   'plotsubjects' - ['on'|'off'] When 'on', plot ERP of all subjects.
%   'noplot'   - ['on'|'off'] When 'on', only return output values. Default
%                is 'off'.
%   'topoplotopt' - [cell array] options for topoplot plotting.
%
% Optional inputs for component plotting:
%   'clusters' - [numeric vector|'all'] indices of clusters to plot.
%                If no component indices ('comps' below) are given, the average 
%                ERPs of the requested clusters are plotted in the same figure, 
%                with ERPs for different conditions (and groups if any) plotted 
%                in different colors. In 'comps' (below) mode, ERPS for each 
%                specified cluster are plotted in separate figures (one per 
%                condition), each overplotting cluster component ERPs plus the
%                average cluster ERP in bold. Note this parameter has no effect 
%                if the 'comps' option (below) is used. {default: 'all'}
%   'comps'    - [numeric vector|'all'] indices of the cluster components to plot.
%                Note that 'comps', 'all' is equivalent to 'plotsubjects', 'on'.
%
% Other optional inputs:
%   'key','val' - All optional inputs to POP_ERPPARAMS are also accepted here
%                 to plot subset of time, statistics etc. The values used by default
%                 are the ones set using POP_ERPPARAMS and stored in the
%                 STUDY structure.
%
% Outputs:
%   STUDY      - the input STUDY set structure with plotted cluster mean
%                ERPs data to allow quick replotting 
%   erpdata    - [cell] ERP data for each condition, group and subjects.
%                size of cell array is [nconds x ngroups]. Size of each element
%                is [times x subjects] for data channels or [times x components]
%                for component clusters. This array may be gicen as input 
%                directly to the STATCOND function or STD_STAT function
%                to compute statistics.
%   erptimes   - [array] ERP time point latencies.
%   pgroup     - [array or cell] p-values group statistics. Output of the 
%                STATCOND function.
%   pcond      - [array or cell] condition statistics. Output of the STATCOND 
%                function.
%   pinter     - [array or cell] groups x conditions statistics. Output of
%                STATCOND function.
%
%   Example:
%            >> [STUDY] = std_erpplot(STUDY,ALLEEG, 'clusters', 2, 'comps', 'all');
%               % Plot cluster-2 component ERPs plus the mean ERP in bold. 
%
%  See also  POP_CLUSTEDIT, POP_PRECLUST, EEG_CREATEDATA, EEG_PRECLUST, STD_PROPPLOT
%
% Authors: Arnaud Delorme, CERCO, August, 2006-

% Copyright (C) Arnaud Delorme, arno@salk.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, erpdata, alltimes, pgroup, pcond, pinter] = std_erpplot(STUDY, ALLEEG, varargin)

if nargin < 2
    help std_erpplot;
    return;
end
erpdata = []; alltimes = []; 
pgroup = []; pcond = []; pinter = [];

% find datatype and default options
% ---------------------------------
dtype = 'erp';
dsubtype = '';
for ind = 1:2:length(varargin)
    if strcmpi(varargin{ind}, 'datatype')
        dtype = varargin{ind+1}; 
    end
end
if strcmpi(dtype(1:3), 'erp' )
    if length(dtype) > 3, dsubtype = dtype(4:end); dtype = 'erp'; end
elseif strcmpi(dtype(1:4), 'spec')
    if length(dtype) > 4, dsubtype = dtype(5:end); dtype = 'spec'; end
end

% get parameters
% --------------
eval( [ 'tmp = pop_' dtype 'params(STUDY, varargin{:});' ...
        'params = tmp.etc.' dtype 'params; clear tmp;' ] );
statstruct.etc = STUDY.etc; 
statstruct = pop_statparams(statstruct, varargin{:});

% potentially missing fields
% --------------------------
fields     = { 'filter' 'subtractsubjectmean' 'timerange' 'freqrange' 'topotime' 'topofreq' 'averagechan'};
defaultval = { [] 'off' [] [] [] [] };
for ind=1:length(fields)
    if ~isfield(params, fields{ind})
        params = setfield(params, fields{ind}, defaultval{ind}); 
    end
end

% decode parameters
% -----------------
if isempty(varargin)
    tmplocs = eeg_mergelocs(ALLEEG.chanlocs);
    options.channels = { tmplocs.labels };
else
    options = mystruct(varargin);
end
options = myrmfield( options, myfieldnames(params));
options = myrmfield( options, myfieldnames(statstruct.etc.statistics));
options = myrmfield( options, { 'threshold' 'statistics' } ); % for backward compatibility
opt = finputcheck( options, ...
                             { 'design'      'integer' []              STUDY.currentdesign;
                               'plotstderr'  'string'  []              'off';
                               'channels'    'cell'    []              {};
                               'clusters'    'integer' []              [];
                               'datatype'    'string'  {}              'erp';
                               'mode'  'string'  []  '';
                               'comps'  { 'string', 'integer' }  []  [];
                               'statmode'    'string'  { 'subjects','common','trials' } 'subjects';
                               'avgmode'     'string'  { 'mean','rms','median' } 'mean';
                               'plotmode'    'string'  { 'normal','condensed' }  'normal';
                               'unitx'       'string'  { 'ms','Hz' }    'ms';
                               'plotsubjects' 'string' { 'on','off' }  'off';
                               'detachplots' 'string'  { 'on','off' }  params.detachplots;
                               'noplot'      'string'  { 'on','off' }  'off';
                               'topoplotopt' 'cell'    {}              { 'style' 'both' };
                               'subject'     'string'  []              '' }, 'std_erpplot');
if ischar(opt), error(opt); end
if ischar(opt.comps), opt.comps = []; opt.plotsubjects = 'on'; end
if ~isempty(params.topofreq) && strcmpi(opt.datatype, 'spec'),  params.topotime  = params.topofreq; end
if ~isempty(params.freqrange), params.timerange = params.freqrange; end
datatypestr = upper(opt.datatype);
if strcmpi(datatypestr, 'spec'), datatypestr = 'Spectrum'; end
    
% =======================================================================
% below this line, all the code should be non-specific to ERP or spectrum
% =======================================================================
allconditions  = {};
allgroups      = {};
condname       = '';
groupname      = '';
if length(STUDY.design(opt.design).variable) > 0, allconditions = STUDY.design(opt.design).variable(1).value; condname  = STUDY.design(opt.design).variable(1).label; end
if length(STUDY.design(opt.design).variable) > 1, allgroups     = STUDY.design(opt.design).variable(2).value; groupname = STUDY.design(opt.design).variable(2).label;  end

% for backward compatibility
% --------------------------
stats = statstruct.etc.statistics;
stats.fieldtrip.channelneighbor = struct([]); % assumes one channel or 1 component
if isempty(STUDY.design(opt.design).variable)
    stats.paired = { };
else
    stats.paired = { STUDY.design(opt.design).variable(:).pairing };
end
if strcmpi(opt.mode, 'comps'), opt.plotsubjects = 'on'; end
if strcmpi(stats.singletrials, 'off') && ((~isempty(opt.subject) || ~isempty(opt.comps)))
    if strcmpi(stats.condstats, 'on') || strcmpi(stats.groupstats, 'on')
        stats.groupstats = 'off';
        stats.condstats   = 'off'; 
        disp('No statistics for single subject/component, to get statistics compute single-trial measures'); 
    end
end

if ~isempty(params.topotime) && ~isnan(params.topotime(1)) && length(opt.channels) < 5 && isempty(opt.clusters)
    warndlg2(strvcat('ERP parameters indicate that you wish to plot scalp maps', 'Select at least 5 channels to plot topography'));
    return;
end

if ~strcmpi(opt.avgmode, 'mean') && (isempty(opt.channels) || isempty(params.topotime))
    error('Can only change avgmode when plotting scalp topographies')
end

plotcurveopt = {};
if length(opt.clusters) > 1
    plotcurveopt = { 'figure' 'off' }; 
    params.plotconditions = 'together';
    params.plotgroups     = 'together';
    stats.condstats  = 'off'; 
    stats.groupstats = 'off';
end
% if length(opt.channels) > 1 && strcmpi(opt.plotconditions, 'together') && strcmpi(opt.plotgroups, 'together')
%     plotcurveopt = { 'figure' 'off' }; 
%     opt.plotconditions = 'together';
%     opt.plotgroups     = 'together';
%     opt.condstats  = 'off'; 
%     opt.groupstats = 'off';
% end
alpha    = fastif(strcmpi(stats.mode, 'eeglab'), stats.eeglab.alpha, stats.fieldtrip.alpha);
mcorrect = fastif(strcmpi(stats.mode, 'eeglab'), stats.eeglab.mcorrect, stats.fieldtrip.mcorrect);
method   = fastif(strcmpi(stats.mode, 'eeglab'), stats.eeglab.method, ['Fieldtrip ' stats.fieldtrip.method ]);
plotcurveopt = { plotcurveopt{:} ...
   'ylim',           params.ylim, ...
   'threshold',      alpha ...
   'unitx'           opt.unitx, ...
   'filter',         params.filter, ...
   'plotgroups',     params.plotgroups, ...
   'effect',         stats.effect, ...
   'plotconditions', params.plotconditions };

% channel plotting
% ----------------
axcopyflag = 1;
if ~isempty(opt.channels)
    if (isempty(params.topotime) || isnan(params.topotime(1))) && length(opt.channels) > 1 && strcmpi(stats.singletrials, 'on')
        error('Cannot plot several channels on the same figure when using single trial statistics');
    end

    chaninds = 1:length(opt.channels);

    if strcmpi(opt.datatype, 'erp')
        [STUDY, erpdata, alltimes, ~, ~, fileparams] = std_readdata(STUDY, ALLEEG, 'channels', opt.channels(chaninds), 'timerange', params.timerange, ...
                'subject', opt.subject, 'singletrials', stats.singletrials, 'design', opt.design, 'datatype', [dtype dsubtype]);
    else
        [STUDY, erpdata, alltimes, ~, ~, fileparams] = std_readdata(STUDY, ALLEEG, 'channels', opt.channels(chaninds), 'freqrange', params.freqrange, ...
                'subject', opt.subject, 'singletrials', stats.singletrials, 'design', opt.design, 'datatype', [dtype dsubtype], 'rmsubjmean', params.subtractsubjectmean);
    end
    if isfield(fileparams, 'specmode') && ~strcmpi(fileparams.specmode, 'fft'), opt.unitx = [ opt.unitx 'psd' ]; end
    if ~strcmpi(params.averagechan, 'off') && length(chaninds) > 1
        for index = 1:length(erpdata(:))
            if strcmpi(params.averagechan, 'on')
                erpdata{index} = squeeze(mean(erpdata{index},2));
            else
                erpdata{index} = squeeze(sqrt(mean(erpdata{index}.^2,2)));
                opt.unitx = 'rmsms';
            end
        end
        if strcmpi(params.averagechan, 'rms')
            opt.unitx = [ 'rms' opt.unitx ];
        end
    end
    if isempty(erpdata), return; end

    % select specific time
    % --------------------
    if ~isempty(params.topotime) && ~isnan(params.topotime(1))
        [tmp, ti1] = min(abs(alltimes-params.topotime(1)));
        [tmp, ti2] = min(abs(alltimes-params.topotime(end)));
        for condind = 1:length(erpdata(:))
            if ~isempty(erpdata{condind})
                erpdata{condind} = mean(erpdata{condind}(ti1:ti2,:,:),1);
            end
        end
    end

    % compute baseline for spectrum
    % -----------------------------
    if strcmpi(params.subtractsubjectmean, 'on') && strcmpi(opt.datatype, 'spec')
        count    = 0;
        for iSpec = 1:length(erpdata(:))
            if ~isempty(erpdata{iSpec})
                if count == 0, meanspec = zeros(size(erpdata{iSpec},1),1); end
                if strcmpi(stats.singletrials, 'on')
                    meanspec = meanspec + mean(erpdata{iSpec},2);
                else
                    meanspec = meanspec + erpdata{iSpec};
                end
                count = count+1;
            end
        end
        meanspec = meanspec/count;
        erpdata  = cellfun(@(x)bsxfun(@minus, x, meanspec), erpdata, 'uniformoutput', false);
    end

    % compute statistics
    % ------------------
    if (isempty(params.topotime) || any(isnan(params.topotime))) && length(alpha) > 1
        alpha = alpha(1);
    end
    if ~isempty(params.topotime) && all(~isnan(params.topotime))
         statstruct = std_prepare_neighbors(statstruct, ALLEEG, 'channels', opt.channels);
         stats.fieldtrip.channelneighbor = statstruct.etc.statistics.fieldtrip.channelneighbor;
    end
    [pcond, pgroup, pinter] = std_stat(erpdata, stats);
    if (~isempty(pcond) && length(pcond{1}) == 1) || (~isempty(pgroup) && length(pgroup{1}) == 1), pcond = {}; pgroup = {}; pinter = {}; end % single subject STUDY                                
    if ~isempty(params.topotime) && length(opt.channels) > 5 && ndims(erpdata{1}) < 3, pcond = {}; pgroup = {}; pinter = {}; end % topo plotting for single subject
    if strcmpi(opt.noplot, 'on'), return; end
    
    % get titles (not included in std_erspplot because it is not possible
    % to merge channels for that function
    % -----------------------------------
    locsOri = eeg_mergelocs(ALLEEG.chanlocs);
    locs = locsOri(std_chaninds(STUDY, opt.channels(chaninds)));
    if ~strcmpi(params.averagechan, 'off') && length(chaninds) > 1
        if length(chaninds) ~= length(locsOri)
            chanlabels = { locs.labels };
            chanlabels(2,:) = {','};
            chanlabels(2,end) = {''};
            locs(1).labels = [ chanlabels{:} ];
        else
            locs(1).labels = 'All channels';
        end
        locs(2:end) = [];    
    end
    [alltitles, alllegends ] = std_figtitle('threshold', alpha, 'mcorrect', mcorrect, 'condstat', stats.condstats, 'cond2stat', stats.groupstats, ...
                             'statistics', method, 'condnames', allconditions, 'plotsubjects', opt.plotsubjects, 'cond2names', allgroups, 'chanlabels', { locs.labels }, ...
                             'subject', opt.subject, 'valsunit', opt.unitx, 'vals', params.topotime, 'datatype', datatypestr, 'cond2group', params.plotgroups, ...
                             'condgroup', params.plotconditions, 'effect', stats.effect, 'factor1', condname, 'factor2', groupname);

    % plot
    % ----
    indNonEmpty = find(~cellfun(@isempty, erpdata(:)));
    if isempty(indNonEmpty)
        error('All conditions are empty')
    end
    if ~isreal(erpdata{indNonEmpty(1)}(1)) % for spectrum FFT data
        tmperpdata = cellfun(@(x)x.*conj(x), erpdata, 'uniformoutput', false);
    else
        tmperpdata = erpdata;
    end
    if ~isempty(params.topotime) && all(~isnan(params.topotime))
        std_chantopo(tmperpdata, 'groupstats', pgroup, 'condstats', pcond, 'interstats', pinter, 'caxis', params.ylim, ...
                                 'mode', opt.avgmode, 'chanlocs', locs, 'threshold', alpha, 'titles', alltitles, 'topoplotopt', opt.topoplotopt, 'effect', stats.effect);
    else
        std_plotcurve(alltimes, tmperpdata, 'groupstats', pgroup, 'legend', alllegends, 'condstats', pcond, 'interstats', pinter, ...
            'chanlocs', locs, 'titles', alltitles, 'plotsubjects', opt.plotsubjects, 'plotstderr', opt.plotstderr, ...
            'condnames', allconditions, 'groupnames', allgroups, plotcurveopt{:});
    end

    set(gcf,'name',['Channel ' datatypestr ]);
    axcopy(gca);
else 
    if length(opt.clusters) > 1 && strcmpi(stats.singletrials, 'on')
        error('Cannot plot several components on the same figure when using single trial statistics');
    end
    
   % plot component
    % --------------
    if length(opt.clusters) > 1, figure('color', 'w'); end
    nc = ceil(sqrt(length(opt.clusters)));
    nr = ceil(length(opt.clusters)/nc);
    comp_names = {};
    
    for index = 1:length(opt.clusters)

        if length(opt.clusters) > 1, subplot(nr,nc,index); end
        if strcmpi(opt.datatype, 'erp')
            [STUDY, erpdata, alltimes, ~, ~, fileparams] = std_readdata(STUDY, ALLEEG, 'clusters', opt.clusters(index), 'timerange', params.timerange, ...
                    'component', opt.comps, 'singletrials', stats.singletrials, 'design', opt.design, 'datatype', [dtype dsubtype]);
        else
            [STUDY, erpdata, alltimes, ~, ~, fileparams] = std_readdata(STUDY, ALLEEG, 'clusters', opt.clusters(index), 'freqrange', params.freqrange, ...
                    'component', opt.comps, 'singletrials', stats.singletrials, 'design', opt.design, 'datatype', [dtype dsubtype], 'rmsubjmean', params.subtractsubjectmean);
        end
        if isfield(fileparams, 'specmode') && ~strcmpi(fileparams.specmode, 'fft'), opt.unitx = [ opt.unitx 'psd' ]; end
        if isempty(erpdata), return; end

        % plot specific component
        % -----------------------
        if ~isempty(opt.comps)
            comp_names = { STUDY.cluster(opt.clusters(index)).comps(opt.comps) };
            opt.subject = STUDY.datasetinfo(STUDY.cluster(opt.clusters(index)).sets(1,opt.comps)).subject;
        end
        
        % remove NaNs and generate labels
        % -------------------------------
        erpdata2 = erpdata;
        subjects       = { STUDY.datasetinfo(STUDY.cluster(opt.clusters(index)).sets(1,:)).subject };
        for iDat = 1:length(erpdata2(:))
            if all(cellfun(@(x)size(x,2), erpdata2(:)) == length(subjects))  % NOT single trial data
                keepInd = find(~isnan(erpdata2{iDat}(1,:)));
                erpdata2{iDat} = erpdata2{iDat}(:,keepInd);
                tmpSubjects = subjects(keepInd);
                comps       = STUDY.cluster(opt.clusters(index)).comps(keepInd);
            else
                tmpSubjects = subjects;
                comps       = STUDY.cluster(opt.clusters(index)).comps;
            end
            for iKeep = 1:length(tmpSubjects)
                sbtitles{iDat}{iKeep} = [ tmpSubjects{iKeep}  '/IC' num2str(comps(iKeep)) ];
            end
        end
        sbtitles = reshape(sbtitles, size(erpdata2));
        
        [pcond, pgroup, pinter] = std_stat(erpdata2, stats);
        if strcmpi(opt.noplot, 'on'), return; end
            
        [alltitles, alllegends ] = std_figtitle('threshold', alpha, 'plotsubjects', opt.plotsubjects, 'mcorrect', mcorrect, 'condstat', stats.condstats, 'cond2stat', stats.groupstats, ...
                                 'statistics', method, 'condnames', allconditions, 'cond2names', allgroups, 'clustname', STUDY.cluster(opt.clusters(index)).name, 'compnames', comp_names, ...
                                 'subject', opt.subject, 'valsunit', opt.unitx, 'vals', params.topotime, 'datatype', datatypestr, 'cond2group', params.plotgroups, 'condgroup', params.plotconditions, ...
                                 'effect', stats.effect, 'factor1', condname, 'factor2', groupname);
        
        if length(opt.clusters) > 1 && index < length(opt.clusters), alllegends = {}; end
        std_plotcurve(alltimes, erpdata2, 'condnames', allconditions, 'legend', alllegends, 'groupnames', allgroups, 'plotstderr', opt.plotstderr, ...
                                          'titles', alltitles, 'groupstats', pgroup, 'condstats', pcond, 'interstats', pinter, ...
                                          'plotsubjects', opt.plotsubjects, plotcurveopt{:});
%--------------------------------------------------------------------------                                      
        if all([strcmp(opt.plotsubjects,'on') strcmp(opt.detachplots,'on')])
            
             [alltitlestmp] = std_figtitle('threshold', alpha, 'plotsubjects', opt.plotsubjects, 'mcorrect', mcorrect, 'condstat', 'off', 'cond2stat', 'off', ...
                                 'statistics', method, 'condnames', allconditions, 'cond2names', allgroups, 'clustname', STUDY.cluster(opt.clusters(index)).name, 'compnames', comp_names, ...
                                 'subject', opt.subject, 'valsunit', opt.unitx, 'vals', params.topotime, 'datatype', datatypestr, 'cond2group', params.plotgroups, 'condgroup', params.plotconditions);
                             
            handles = findall(0,'Type','Figure', 'Tag','tmp_curvetag');
            std_detachplots('','','data',erpdata2,'figtitles', {alltitlestmp{:}}','sbtitles',sbtitles,'handles', handles, 'filter',params.filter);
            axcopyflag = 0;

        end
%--------------------------------------------------------------------------
    end
    tmpgcf = gcf;
    set(tmpgcf,'name', ['Component ' datatypestr ] );
    if axcopyflag
          haxis = findall(tmpgcf,'type','axes');
        for i= 1: length(haxis)
            axcopy(haxis(i));
        end
    end 
end

% remove fields and ignore fields who are absent
% ----------------------------------------------
function s = myrmfield(s, f)

for index = 1:length(f)
    if isfield(s, f{index})
        s = rmfield(s, f{index});
    end
end

% convert to structure (but take into account cells)
% --------------------------------------------------
function s = mystruct(v)

for index=1:length(v)
    if iscell(v{index})
        v{index} = { v{index} };
    end
end
try
    s = struct(v{:});
catch, error('Parameter error'); end

% convert to structure (but take into account cells)
% --------------------------------------------------
function s = myfieldnames(v)

s = fieldnames(v);
if isfield(v, 'eeglab')
    s2 = fieldnames(v.eeglab);
    s = { s{:} s2{:} };
end
if isfield(v, 'fieldtrip')
    s3 = fieldnames(v.fieldtrip);
    for index=1:length(s3)
        s3{index} = [ 'fieldtrip' s3{index} ];
    end
    s = { s{:} s3{:} };
end
