%
% ENVTOPO - Plot the envelope of a multichannel data epoch, plus envelopes and
%             scalp maps of specified or largest-contributing components. If a 3-D
%             input matrix, operates on the mean of the data epochs. Click on
%             individual axes to examine them in detail. The black lines represent
%             the max and min values across all channels at each time point.
%             The blue shading represents the max and min contributions of
%             the selected components tothose channels. The paired colored lines
%             represent the max and min contributions of the indicated component
%             across all channels.
% Usage:
%             >> envtopo(data,weights,'chanlocs',file_or_struct);
%             >> [cmpvarorder,cmpvars,cmpframes,cmptimes,cmpsplotted,sortvar] ...
%                                     = envtopo(data, weights, 'key1', val1, ...);
% Inputs:
%  data        = single data epoch (chans,frames), else it a 3-D epoched data matrix
%                (chans,frames,epochs) ->  processes the mean data epoch.
%  weights     = linear decomposition (unmixing) weight matrix. The whole matrix
%                should be passed to the function here.
%                    Ex: (EEG.icaweights*EEG.icasphere)
% Required keyword:
%  'chanlocs'  = [string] channel location filename or EEG.chanlocs structure.
%                For more information, see >> topoplot example
%
% Optional inputs:
%  'compnums'  = [integer array] vector of component indices to use in the
%                  calculations and to select plotted components from
%                  {default|[]: all}
%  'compsplot' = [integer] the number of largest contributing components to plot.
%                  compnums in the latter case is restricted in size by the
%                  internal variable MAXTOPOS (20) {default|[] -> 7}
%  'subcomps'  = [integer vector] indices of comps. to remove from the whole data
%                  before plotting. 0 -> Remove none. [] -> If 'compnums'
%                  also listed, remove *all* except 'compnums' {default: 0}
%  'limits'    = 0 or [minms maxms] or [minms maxms minuV maxuV]. Specify
%                  start/end plot (x) limits (in ms) and min/max y-axis limits
%                  (in uV). If 0, or if both minmx & maxms == 0 -> use latencies
%                  from 'timerange' (else 0:frames-1). If both minuV and
%                  maxuV == 0 -> use data uV limits {default: 0}
%  'timerange' = start and end input data latencies (in ms) {default: from 'limits'
%                  if any}. Note: Does NOT select a portion of the input data,
%                  just makes time labels.
%  'limcontrib' = [minms maxms]  time range (in ms) in which to rank component
%                  contribution (boundaries shown with thin dotted lines)
%                  {default|[]|[0 0] -> plotting limits}
%  'sortvar'   = ['mp'|'pv'|'pp'|'rp'] {default:'mp'}
%                  'mp', sort components by maximum mean back-projected power
%                  in the 'limcontrib' time range: mp(comp) = max(Mean(back_proj.^2));
%                  where back_proj = comp_map * comp_activation(t) for t in 'limcontrib'
%                  'pv', sort components by percent variance accounted for (EEG_PVAF)
%                    pvaf(comp) = 100-100*mean(var(data - back_proj))/mean(var(data));
%                  'pp', sort components by percent power accounted for (ppaf)
%                    ppaf(comp) = 100-100*Mean((data - back_proj).^2)/Mean(data.^2);
%                  'rp', sort components by relative power
%                    rp(comp) = 100*Mean(back_proj.^2)/Mean(data.^2);
%  'title'     = [string] plot title {default|[] -> none}
%  'plotchans' = [integer array] data channels to use in computing contributions and
%                  envelopes, and also for making scalp topo plots
%                  {default|[] -> all}, by calling TOPOPLOT.
%  'voffsets'  = [float array] vertical line extensions above the data max to
%                  disentangle plot lines (left->right heads, values in y-axis units)
%                  {default|[] -> none}
%  'colors'    = [string] filename of file containing colors for envelopes, 3 chars
%                  per line, (. = blank). First color should be "w.." (white)
%                  Else, 'bold' -> plot default colors in thick lines.
%                  {default|[] -> standard Matlab color order}
%  'fillcomp'  = int_vector>0 -> fill the numbered component envelope(s) with
%                  solid color. Ex: [1] or [1 5] {default|[]|0 -> no fill}
% 'plotproj'   = [1|0] Plot channel projections if only one component projection is
%                   plotted. {default: 0}
% 'fillcolor'  = Three elements RGB vector of the color to fill the component envelope
%                   if 'fillcomp' is set. {default|[.815 .94 1] %light blue}
%  'vert'      = vector of times (in ms) at which to plot vertical dashed lines
%                  {default|[] -> none}
%  'icawinv'   = [float array] inverse weight matrix. Normally computed by inverting
%                  the weights*sphere matrix (Note: If some components have been
%                  removed, the pseudo-inverse does not represent component maps
%                  accurately).
%  'icaact'    = [float array] component activations. {default: computed from the
%                  input weight matrix}
%  'envmode'   = ['avg'|'rms'] compute the average envelope or the root mean square
%                  envelope {default: 'avg'}
%  'sumenv'    = ['on'|'off'|'fill'] 'fill' -> show the filled envelope of the summed
%                  projections of the selected components; 'on' -> show the envelope
%                  only {default: 'fill'}
%  'actscale'  = ['on'|'off'] scale component scalp maps by maximum component activity
%                  in the designated (limcontrib) interval. 'off' -> scale scalp maps
%                  individually using +/- max(abs(map value)) {default: 'off'}
%  'dispmaps'  = ['on'|'off'] display component numbers and scalp maps {default: 'on'}
%  'topoplotkey','val' = optional additional TOPOPLOT arguments {default: none}
%  'axisoff'   = [real] percent of the figure y-dimension to be covered by the axis
%                 for the envelopes. Values are restricted to the range [0.60 1]{default: 0.6}
%
% 'limcontribweight' = [real] lineweight of limonctrib vertical lines.{default: 1.2}
% 'vertweight'       = [real] lineweight of specified vertical lines {default: 2}
%
% Outputs:
%
%  cmpvarorder = component numbers in decreasing order of max variance in data
%  cmpvars     = ('sortvar') max power for all components tested, sorted
%                   from highest to lowest. See 'sortvar' 'mp'
%  cmpframes   = frames of comvars for each component plotted
%  cmptimes    = times of compvars for each component plotted
%  cmpsplotted = indices of components plotted.
%                       unsorted_compvars = compvars(compsplotted);
%  sortvar      = The computed data used to sort components with.
%                 See 'sortvar' option above.
%
% Notes:
%  To label maps with other than component numbers, put four-char strings into
%  a local (pwd) file named 'envtopo.labels' (using . = space) in time-order
%  of their projection maxima
%
% Authors: Scott Makeig & Arnaud Delorme, SCCN/INC/UCSD, La Jolla, 3/1998
%
% See also: TIMTOPO AXCOPY

% Copyright (C) 3-10-98 from timtopo.m Scott Makeig, SCCN/INC/UCSD, scott@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.

% Edit History:
% 3-18-98 fixed bug in LineStyle for fifth component, topoplot maxproj with
%         correct orientations, give specified component number labels -sm
% 4-28-98 plot largest components, ranked by max projected variance -sm
% 4-30-98 fixed bug found in ICADEMO -sm
% 5-08-98 fixed bug found by mw () -sm
% 5-23-98 made vert. line styles for comps 6 & 11 correct -sm
% 5-30-98 added 'envtopo.labels' option -sm
% 5-31-98 implemented plotchans arg -sm
% 7-13-98 gcf->gca to allow plotting in subplots -sm
% 9-18-98 worked more to get plotting in subplot to work -- no luck yet! -sm
% 2-22-99 draw oblique line to max env value if data clipped at max proj -sm
% 2-22-99 added colorfile -sm
% 4-17-99 added support for drawing in subplots -t-pj
% 10-29-99 new versions restores search through all components for max 7 and adds
%          return variables (>7 if specified. Max of 7 comp envs still plotted. -sm
% 11-17-99 debugged new version -sm
% 12-27-99 improved help msg, moved new version to distribution -sm
% 01-21-00 added 'bold' option for colorfile arg -sm
% 02-28-00 added fill_comp_env arg -sm
% 03-16-00 added AXCOPY -sm & tpj
% 05-02-00 added vert option -sm
% 05-30-00 added option to show "envelope" of only 1 channel -sm
% 09-07-00 added [-n] option for compnums, added BOLD_COLORS as default -sm
% 12-19-00 updated ICAPROJ args -sm
% 12-22-00 trying 'axis square' for topoplots -sm
% 02-02-01 fixed bug in printing component 6 env line styles -sm
% 04-11-01 added [] default option for args -sm
% 01-25-02 reformated help & license, added links -ad
% 03-15-02 added readlocs and the use of eloc input structure -ad
% 03-16-02 added all topoplot options -ad

function [compvarorder,compvars,compframes,comptimes,compsplotted,sortvar] = envtopo(data,weights,varargin)

% icadefs;    % read toolbox defaults

sortvar = [];
all_bold = 0;
BOLD_COLORS = 1;    % 1 = use solid lines for first 5 components plotted
                    % 0 = use std lines according to component rank only
% FILL_COMP_ENV = 0;  % default no fill
%FILLCOLOR   = [.815 .94 1]; % use lighter blue for better env visibility
MAXTOPOS = 20;      % max topoplots to plot
% VERTWEIGHT = 2.0;  % lineweight of specified vertical lines
% LIMCONTRIBWEIGHT = 1.2; % lineweight of limonctrib vertical lines
MAX_FRAMES = 10000; % maximum frames to plot
MAXENVPLOTCHANS = 10;
xmin = 0; xmax = 0;

if nargin < 2
   help envtopo
   return
end

if nargin <= 2 || ischar(varargin{1})
	% 'key' 'val' sequences
	fieldlist = { 'chanlocs'      ''         []                       [] ;
				  'title'         'string'   []                       '';
				  'limits'        'real'     []                       0;
				  'timerange'     'real'     []                       [];
				  'plotchans'     'integer'  [1:size(data,1)]         [] ;
				  'icawinv'       'real'     []                       pinv(weights) ;
				  'icaact'        'real'     []                       [] ;
				  'voffsets'      'real'     []                       [] ;
				  'vert'          'real'     []                       [] ;
				  'fillcomp'      'integer'  []                       0 ;
				  'figure'        'integer'  []                       [] ;
				  'colorfile'     'string'   []                       '' ;
				  'colors'        'string'   []                       '' ;
				  'compnums'      'integer'  []                       [];
				  'compsplot'     'integer'  []                       7;
				  'subcomps'      'integer'  []                       0;
				  'envmode'       'string'   {'avg','rms'}            'avg';
				  'dispmaps'      'string'   {'on','off'}             'on';
				  'pvaf'          'string'   {'mp','mv','on','rp','rv','pv','pvaf','pp','off',''} '';
				  'sortvar'       'string'   {'mp','mv','rp','rv','pv','pvaf','pp'} 'mp';
				  'actscale'      'string'   {'on','off'}             'off';
				  'limcontrib'    'real'     []                       0;
				  'topoarg'       'real'     []                       0;
				  'sumenv'        'string'   {'on','off','fill'}      'fill';
                  'axisoff'       'real'     [0.6 1]               0.6;
                  'fillcolor'     'real'     []                       [.815 .94 1];
                  'limcontribweight'  'real' []                       1.2;
                  'plotproj'          'real' [0 1]                    0;
                  'vertweight'        'real' []                       2};

	% Note: Above, previous 'pvaf' arguments 'on' -> 'pv', 'off' -> 'rv'
	%       for backwards compatibility 11/2004 -sm

	[g varargin] = finputcheck( varargin, fieldlist, 'envtopo', 'ignore');
	if ischar(g), error(g); end
    if g.plotproj && strcmp(g.sumenv, 'fill'), g.sumenv = 'on'; end

else % dprecated - old style input args
	if nargin > 3,    g.chanlocs = varargin{1};
	else              g.chanlocs = [];
	end
        if ischar(varargin{2}), help envtopo; return; end
	if nargin > 4,	  g.limits = varargin{2};
	else              g.limits = 0; % [];
	end
        if ischar(varargin{3}), help envtopo; return; end
	if nargin > 5,    g.compnums = varargin{3};
	else              g.compnums = [];
	end
        if ~ischar(varargin{4}), help envtopo; return; end
	if nargin > 6,    g.title = varargin{4};
	else              g.title = '';
	end
        if ischar(varargin{5}), help envtopo; return; end
	if nargin > 7,    g.plotchans = varargin{5};
	else              g.plotchans = [];
	end
        if ischar(varargin{6}), help envtopo; return; end
	if nargin > 8,    g.voffsets = varargin{6};
	else              g.voffsets = [];
	end
        if ischar(varargin{7}), help envtopo; return; end
	if nargin > 9,    g.colorfile = varargin{7};
	else              g.colorfile = '';
	                  g.colors = '';
	end
        if ischar(varargin{8}), help envtopo; return; end
	if nargin > 10,   g.fillcomp = varargin{8};
	else              g.fillcom = 0;
	end
        if ischar(varargin{9}), help envtopo; return; end
	if nargin > 11,   g.vert = varargin{9};
	else              g.vert = [];
	end
    if nargin > 12, varargin =varargin(10:end); end
    g.sumenv = 'on';
    g.sortvar = 'mp';
    g.pvaf = [];
    g.timerange = [];
    g.icaact = [];
    g.limcontrib = 0;
    g.icawinv = pinv(weights);
    g.subcomps = 0;
    g.envmode = 'avg';
    g.dispmaps = 'on';
end
if ~isempty(g.figure), figure(g.figure); end;        % remember the current figure (for Matlab 7.0.0 bug)

if ~isempty(g.pvaf)
	g.sortvar = g.pvaf; % leave deprecated g.pvaf behind.
end

if strcmpi(g.sortvar,'on') || strcmpi(g.sortvar,'pvaf') || strcmpi(g.sortvar,'mv')
   g.sortvar = 'mp'; % update deprecated flags
end
if strcmpi(g.sortvar,'off') || strcmp(g.sortvar,'rv')
   g.sortvar = 'rp';
end

%
% Check input flags and arguments
%
if ndims(data) == 3
    data = mean(data,3); % average the data if 3-D
end
[chans,frames] = size(data);

if frames > MAX_FRAMES
   error('number of data frames to plot too large!');
end

if ischar(g.chanlocs)
    g.chanlocs = readlocs(g.chanlocs);  % read channel location information
    if length(g.chanlocs) ~= chans
     fprintf(...
      'envtopo(): locations for the %d data channels not in the channel location file.\n', ...
        chans);
        return
    end
end
% Checking dimension of chanlocs
if length(g.chanlocs) > size(data,1)
    fprintf(2,['\n envtopo warning: Dimensions of data to plot and channel location are not consistent\n' ...
        '                 As a result, the plots generated can be WRONG\n'...
        '                 If you are providing the path to your channel location file. Make sure\n'...
        '                 to load the file first, and to provide as an input only the channels that\n'...
        '                 correspond to the data to be plotted, otherwise just provide a valid chanlocs\n ']);
elseif length(g.chanlocs) > size(data,1)
        fprintf(2,['\n envtopo error: Dimensions of data to plot and channel location are not consistent\n' ...
        '                 Check the dimension of the channel location provided\n'...
        '                 Aborting plot ...\n']);
    exit;
end

if ~isempty(g.colors)
    g.colorfile = g.colors; % retain old usage 'colorfile' for 'colors' -sm 4/04
end

if ~isempty(g.vert)
   g.vert = g.vert/1000; % convert from ms to s
end
%
%%%%%% Collect information about the gca, then delete it %%%%%%%%%%%%%
%
uraxes = gca; % the original figure or subplot axes
pos=get(uraxes,'Position');
axcolor = get(uraxes,'Color');
delete(gca)

%
%%% Convert g.timerange, g.limits and g.limcontrib to sec from ms %%%%
%
g.timerange = g.timerange/1000;   % the time range of the input data
g.limits(1) = g.limits(1)/1000;   % the time range to plot
if length(g.limits) == 1   % make g.limits at least of length 2
    g.limits(1) = 0; g.limits(2) = 0;
else
    g.limits(2) = g.limits(2)/1000;  %
end
g.limcontrib = g.limcontrib/1000; % the time range in which to select largest components

%
%%%%%%%%%%%% Collect time range information %%%%%%%%%%%%%%%%%%%%%%%%%%
%
if length(g.limits) == 3 || length(g.limits) > 4 % if g.limits wrong length
   fprintf('envtopo: limits should be 0, [minms maxms], or [minms maxms minuV maxuV].\n');
end

xunitframes = 0; % flag plotting if xmin & xmax are in frames instead of sec
if ~isempty(g.timerange)   % if 'timerange' given
    if g.limits(1)==0 && g.limits(2)==0
         g.limits(1) = min(g.timerange); % if no time 'limits
         g.limits(2) = max(g.timerange); % plot whole data epoch
    end
else % if no 'timerange' given
    if g.limits(1)==0 && g.limits(2)==0 % if no time limits as well,
         fprintf('\nNOTE: No time limits given: using 0 to %d frames\n',frames-1);
         g.limits(1) = 0;
         g.limits(2) = frames-1;
         xunitframes     = 1; % mark frames as time unit instead of sec
    end
end

if isempty(g.timerange)
  xmin = g.limits(1); % (xmin, xmax) are data limits in sec
  xmax = g.limits(2);
else
  xmin = g.timerange(1); % (xmin, xmax) are data limits in sec
  xmax = g.timerange(2);
end

pmin = g.limits(1); % plot min and max sec
if pmin < xmin
   pmin = xmin;     % don't allow plotting beyond the data limits
end
pmax = g.limits(2);
if pmax > xmax
   pmax = xmax;
end

dt = (xmax-xmin)/(frames-1);  % sampling interval in sec
times=xmin*ones(1,frames)+dt*(0:frames-1); % time points in sec

%
%%%%%%%%%%%%%%% Find limits of the component selection window %%%%%%%%%
%
if any(g.limcontrib ~= 0)
    if xunitframes
       g.limcontrib = g.limcontrib*1000; % if no time limits, interpret
    end                                  % limcontrib as frames
    if g.limcontrib(1)<xmin
          g.limcontrib(1) = xmin;
    end
    if g.limcontrib(2)>xmax
          g.limcontrib(2) = xmax;
    end
    srate = (frames-1)/(xmax-xmin);
    limframe1  = round((g.limcontrib(1)-xmin)*srate)+1;
    limframe2  = round((g.limcontrib(2)-xmin)*srate)+1;
    g.vert(end+1) =  g.limcontrib(1);
    g.vert(end+1) =  g.limcontrib(2);
else
    limframe1 = 1;
    limframe2 = frames;
end

%
%%%%%%%%%%%%%%%%%%%%% Read line color information %%%%%%%%%%%%%%%%%%%%%
%
ENVCOLORS = strvcat('w..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..','m..','c..','r..','g..','b..');

if isempty(g.colorfile)
    g.colorfile = ENVCOLORS; % use default color order above
elseif ~ischar(g.colorfile)
      error('Color file name must be a string.');
end
if strcmpi(g.colorfile,'bold')
       all_bold = 1;
       g.colorfile = ENVCOLORS; % default colors
end
if exist(g.colorfile) == 2  % if an existing file
        cid = fopen(g.colorfile,'r');
        if cid <3,
            error('cannot open color file');
        else
            colors = fscanf(cid,'%s',[3 MAXENVPLOTCHANS]);
            colors = colors';
        end
else
        colors = g.colorfile;
end
[r c] = size(colors);
      for i=1:r
        for j=1:c
          if colors(i,j)=='.',
            if j==1
              error('Color file should have color letter in 1st column.');
            elseif j==2
              colors(i,j)='-';
            elseif j>2
              colors(i,j)=' ';
            end
          end
        end
      end
colors(1,1) = 'k'; % make sure 1st color (for data envelope) is black

%
%%%%%%%%%%%%%%%% Check other input variables %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
[wtcomps,wchans] = size(weights);
if wchans ~= chans
     error('Sizes of weights and data do not agree');
end
if wtcomps ~= chans
   fprintf('Number of components not the same as number of channels.\n');
   fprintf('  - component scalp maps and time courses may not be correct.\n');
end

if isempty(g.voffsets) || ( size(g.voffsets) == [1,1] && g.voffsets(1) == 0 )
    g.voffsets = zeros(1,MAXTOPOS);
end
if isempty(g.plotchans) || g.plotchans(1)==0
    g.plotchans = 1:chans;
end
if max(g.plotchans) > chans || min(g.plotchans) < 1
    error('invalid ''plotchan'' index');
end

if g.compsplot < 0
   g.compsplot = abs(g.compsplot);
end

if g.compnums < 0 % legacy syntax
   g.compsplot = abs(g.compnums);
   g.compnums = [];
end
if isempty(g.compnums) || g.compnums(1) == 0
    g.compnums = 1:wtcomps; % by default, select from all components
end

if g.compsplot > MAXTOPOS
    fprintf('Can only plot a maximum of %d components.\n',MAXTOPOS);
    return
else
    MAXTOPOS = g.compsplot;
end

if max(g.compnums) > wtcomps || min(g.compnums)< 1
    error('Keyword ''compnums'' out of range (1 to %d)', wtcomps);
end

g.subcomps = abs(g.subcomps); % don't pass negative channel numbers
if max(g.subcomps) > wtcomps
    error('Keyword ''subcomps'' argument out of bounds');
end

%
%%%%%%%%%%%%%%% Subtract components from data if requested %%%%%%%%%%%%%
%

ncomps = length(g.compnums);

if isempty(g.subcomps) % remove all but compnums
     g.subcomps = 1:wtcomps;
     g.subcomps(g.compnums) = [];
else
  % g.subcomps 0    -> subtract no comps
  %            list -> subtract subcomps list
  if min(g.subcomps) < 1
      if length(g.subcomps) > 1
         error('Keyword ''subcomps'' argument incorrect.');
      end
      g.subcomps = [];   % if subcomps contains a 0 (or <1), don't remove components
  elseif max(g.subcomps) > wtcomps
      error('Keyword ''subcomps'' argument out of bounds.');
  end
end

g.icaact = weights*data;
if ~isempty(g.subcomps)
  fprintf('Subtracting requested components from plotting data: ');
  for k = 1:length(g.subcomps)
      fprintf('%d ',g.subcomps(k));
      if ~rem(k,32)
         fprintf('\n');
      end
  end
  fprintf('\n');
  g.icaact(g.subcomps,:) = zeros(length(g.subcomps),size(data,2));
end

%
%%%%%%%%%%%%%%%%%%%%%%%%%%% Process components %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

for i=1:ncomps-1
    if g.compnums(i) == 0
	       fprintf('Removing component number 0 from compnums.\n');
	       g.compnums(i)=[];
    elseif g.compnums(i)>wtcomps
	       fprintf('compnums(%d) > number of comps (%d)?\n',i,wtcomps);
	       return
    end
    for j=i+1:ncomps
	    if g.compnums(i)==g.compnums(j)
	       fprintf('Removing repeated component number (%d) in compnums.\n',g.compnums(i));
	       g.compnums(j)=[];
            end
    end
end

limitset = 0;
if isempty(g.limits)
  g.limits = 0;
end
if length(g.limits)>1
  limitset = 1;
end

%
%%%%%%%%%%%%%%% Compute plotframes and envdata %%%%%%%%%%%%%%%%%%%%%
%
ntopos = length(g.compnums);
if ntopos > MAXTOPOS
      ntopos = MAXTOPOS; % limit the number of topoplots to display
end

if max(g.compnums) > wtcomps || min(g.compnums)< 1
      fprintf(...
       'envtopo(): one or more compnums out of range (1,%d).\n',wtcomps);
      return
end

plotframes = ones(ncomps);

% toby 2.16.2006: maxproj will now contain all channel info, in case
%                 plotgrid is called in topoplot.
%                 NOT maxproj = zeros(length(g.plotchans),ncomps);
maxproj = zeros(chans,ncomps);

%
% first, plot the data envelope
%
envdata = zeros(2,frames*(ncomps+1));
envdata(:,1:frames) = envelope(g.icawinv(g.plotchans,:)*g.icaact, g.envmode);

fprintf('Data epoch is from %.0f ms to %.0f ms.\n',1000*xmin,1000*xmax);
fprintf('Plotting data from %.0f ms to %.0f ms.\n',1000*xmin,1000*xmax);
fprintf('Comparing maximum projections for components:  \n');
        if ncomps>32
           fprintf('\n');
        end

compvars = zeros(1,ncomps);
mapsigns = zeros(1,ncomps);

%
% Compute frames to plot
%
sampint  = (xmax-xmin)/(frames-1);     % sampling interval in sec
times    = xmin:sampint:xmax;          % make vector of data time values

[v minf] = min(abs(times-pmin));
[v maxf] = min(abs(times-pmax));
pframes  = minf:maxf;         % frames to plot
ptimes   = times(pframes);    % times to plot
if limframe1 < minf
   limframe1 = minf;
end
if limframe2 > maxf
   limframe2 = maxf;
end

%
%%%%%%%%%%%%%% find max variances and their frame indices %%%%%%%%%%%
%

if strcmp(g.sortvar,'pv') %Changed -Jean
	% Variance of the data in the interval, for calculating sortvar.
	vardat = mean(var(data(g.plotchans,limframe1:limframe2),1));
else
	% Compute data rms for sortvar
	powdat = mean(mean(data(g.plotchans,limframe1:limframe2).^2));
end

for c = 1:ncomps

      if isempty(g.icaact) % make the back-projection of component c

          % Changed to include all channels in computation for use in
          % topoplot, particularly with plotgrid option. toby 2.16.2006
          proj = g.icawinv(:,g.compnums(c))*weights(g.compnums(c),:)*data;
      else
          proj = g.icawinv(:,g.compnums(c))*g.icaact(g.compnums(c),:);
      end;

      % save the comp envelope for plotting component waveforms
      envdata(:,c*frames+1:(c+1)*frames) = envelope(proj(g.plotchans,:), g.envmode);

      % Find the frame (timepoint) of largest rms component value
      % and the relative value to those channels defined by plotchans.
      if length(g.plotchans) > 1
        [maxval,maxi] = max(mean((proj(g.plotchans,limframe1:limframe2)).^2));
      else % g.plotchans == 1 --> find absmax value
        [maxval,maxi] = max((abs(proj(g.plotchans,limframe1:limframe2))));
      end
      maxi = maxi+limframe1-1;

      % plotframes and compvars are needed for plotting the lines indicating
      % the timepoint a topoplot refers to.
      plotframes(c) = maxi;
      compvars(c)   = maxval;       % find value of max variance for comp c
      maxproj(:,c)  = proj(:,maxi); % maxproj now contains all channels, to handle
                                    % the 'plotchans'/topoplot'gridplot' conflict.
									% Toby 2.17.2006
      %
      %%%%%% Calculate sortvar, used to sort the components %%%%%%%%%%%
      %
      if strcmpi(g.sortvar,'mp')  % Maximum Power of backproj
          sortvar(c) = maxval;
          fprintf('IC%1.0f maximum mean power of back-projection: %g\n',c,sortvar(c));

      elseif strcmpi(g.sortvar, 'pv')   % Percent Variance
          % toby 2.19.2006: Changed to be consistent with eeg_pvaf().
          sortvar(c) = 100-100*mean(var(data(g.plotchans,limframe1:limframe2)...
                        - proj(g.plotchans,limframe1:limframe2),1))/vardat;
          fprintf('IC%1.0f percent variance accounted for(pvaf): %2.2f%%\n',c,sortvar(c));

      elseif strcmpi(g.sortvar,'pp')    % Percent Power
          sortvar(c) = 100-100*mean(mean((data(g.plotchans,limframe1:limframe2)...
                        - proj(g.plotchans,limframe1:limframe2)).^2))/powdat;
          fprintf('IC%1.0f percent power accounted for(ppaf): %2.2f%%\n',c,sortvar(c));

      elseif strcmpi(g.sortvar,'rp')    % Relative Power
          sortvar(c) = 100*mean(mean((proj(g.plotchans,limframe1:limframe2)).^2))/powdat;
          fprintf('IC%1.0f relative power of back-projection: %g\n',c,sortvar(c));
      else
          error('''sortvar'' argument unknown');
      end

end % component c
fprintf('\n');

%
%%%%%%%%%%%%%%% Compute component selection criterion %%%%%%%%%%%%%%%%%%%%%%%%%%
%

% compute sortvar
if ~xunitframes
  fprintf('  in the interval %3.0f ms to %3.0f ms.\n',...
					1000*times(limframe1),1000*times(limframe2));
end

[sortsortvar spx] = sort(sortvar);
sortsortvar = sortsortvar(end:-1:1);
spx      = spx(end:-1:1);
npercol = ceil(ncomps/3);

%
%%%%%%%%%%%%%%%%%%%%%%%%% Sort the components %%%%%%%%%%%%%%%%%%%%%%%%%%%
%

[tmp,compx]  = sort(sortvar');           % sort compnums on sortvar (as defined by input
                                      % 'sortvar', default is 'mp').
compx        = compx(ncomps:-1:1);    % reverse order of sort
compvars     = compvars(ncomps:-1:1)';% reverse order of sort (output var)
compvarorder = g.compnums(compx);     % actual component numbers (output var)
plotframes   = plotframes(compx);     % plotted comps have these max frames
compframes   = plotframes';           % frame of max variance in each comp (output var)
comptimes    = times(plotframes(compx)); % time of max variance in each comp (output var)
compsplotted = compvarorder(1:ntopos); % (output var)

%
%%%%%%%%%%%%%%%%%%%%%%%% Reduce to ntopos %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

[plotframes,ifx] = sort(plotframes(1:ntopos));% sort plotframes on their temporal order
plottimes  = times(plotframes);       % convert to times in ms
compx      = compx(ifx);              % indices into compnums, in plotting order
maporder   = g.compnums(compx);       % comp. numbers, in plotting order (l->r)
maxproj    = maxproj(:,compx);        % maps in plotting order

vlen = length(g.voffsets); % extend voffsets if necessary
while vlen< ntopos
  g.voffsets = [g.voffsets g.voffsets(vlen)]; % repeat last offset given
  vlen=vlen+1;
end

head_sep = 1.2;
topowidth = pos(3)/(ntopos+(ntopos-1)/5); % width of each topoplot
if topowidth > 0.20    % adjust for maximum height
    topowidth = 0.2;
end

if rem(ntopos,2) == 1  % odd number of topos
   topoleft = pos(3)/2 - (floor(ntopos/2)*head_sep + 0.5)*topowidth;
else % even number of topos
   topoleft = pos(3)/2 - (floor(ntopos/2)*head_sep)*topowidth;
end

%
%%%%%%%%%%%%%%%%%%%% Print times and frames of comp maxes %%%%%%%%%%%%%%
%

% fprintf('\n');
fprintf('Plotting envelopes of %d component projections.\n',ntopos);
if length(g.plotchans) ~= chans
  fprintf('Envelopes computed from %d specified data channels.\n',...
      length(g.plotchans));
end

fprintf('Topo maps will show components: ');
for t=1:ntopos
  fprintf('%4d  ',maporder(t));
end

fprintf('\n');
if ~xunitframes
  fprintf('    with max var at times (ms): ');
  for t=1:ntopos
    fprintf('%4.0f  ',1000*plottimes(t));
  end
  fprintf('\n');
end

fprintf('                  epoch frames: ');
for t=1:ntopos
   fprintf('%4d  ',limframe1-1+plotframes(t));
end
fprintf('\n');

fprintf('    Component sortvar in interval:  ');
for t=1:ntopos
     fprintf('%4.2f ',sortvar(t));
end
fprintf('\n');

sumproj = zeros(size(data(g.plotchans,:))); % toby 2.21.2006 REDUNDANT CALCULATIONS!
for n = 1:ntopos
  if isempty(g.icaact)
      sumproj = sumproj + ...
		g.icawinv(g.plotchans,maporder(n))*weights(maporder(n),:)*data;
  else
      sumproj = sumproj + g.icawinv(g.plotchans,maporder(n))*g.icaact(maporder(n),:);
       % updated -sm 11/04
  end; % Note: sumproj here has only g.plotchans
end
rmsproj = mean(mean((data(g.plotchans,limframe1:limframe2).^2))); % find data rms in interval

if strcmpi(g.sortvar,'rp')
 	sumppaf = mean(mean(sumproj(:,limframe1:limframe2).^2));
    sumppaf = 100*sumppaf/rmsproj;
    ot   = 'rp';
elseif strcmpi(g.sortvar,'pv')
    sumppaf = mean(var((data(g.plotchans,limframe1:limframe2) ...
                                  - sumproj(:,limframe1:limframe2)),1));
    sumppaf = 100-100*sumppaf/vardat;
    ot   = 'pvaf';
else
   sumppaf = mean(mean((data(g.plotchans,limframe1:limframe2) ...
                                  - sumproj(:,limframe1:limframe2)).^2));
    sumppaf = 100-100*sumppaf/rmsproj;
    ot   = 'ppaf';
end

if ~xunitframes
   fprintf('    Summed component ''%s'' in interval [%4g %4g] ms: %4.2f%%\n',...
					ot, 1000*times(limframe1),1000*times(limframe2), sumppaf);
end

%
% Collect user-supplied Y-axis information
% Edited and moved here from 'Collect Y-axis information' section below -Jean
%
if length(g.limits) == 4
     if g.limits(3)~=0 || g.limits(4)~=0 % collect plotting limits from 'limits'
	 ymin = g.limits(3);
	 ymax = g.limits(4);
         ylimset = 1;
     end
else
  ylimset = 0; % flag whether hard limits have been set by the user
  ymin = min(min(g.icawinv(g.plotchans,:)*g.icaact(:,pframes))); % begin by setting limits from plotted data
  ymax = max(max(g.icawinv(g.plotchans,:)*g.icaact(:,pframes)));
end

fprintf('    Plot limits (sec, sec, uV, uV) [%g,%g,%g,%g]\n\n',xmin,xmax, ymin,ymax);

%
%%%%%%%%%%%%%%%%%%%%% Plot the data envelopes %%%%%%%%%%%%%%%%%%%%%%%%%
%
BACKCOLOR = [0.7 0.7 0.7];
FONTSIZE=12;
FONTSIZEMED=10;
FONTSIZESMALL=8;
newaxes=axes('position',pos);
axis off
set(newaxes,'FontSize',FONTSIZE,'FontWeight','Bold','Visible','off','Color',BACKCOLOR);
delete(newaxes) %XXX

% site the plot at bottom of the current axes
axe = axes('Position',[pos(1) pos(2) pos(3) g.axisoff*pos(4)],...
           'FontSize',FONTSIZE,'FontWeight','Bold');

g.limits = get(axe,'Ylim');
set(axe,'GridLineStyle',':')
set(axe,'Xgrid','off')
set(axe,'Ygrid','on')
axes(axe)
set(axe,'Color',axcolor);

%
%%%%%%%%%%%%%%%%% Plot the envelope of the summed selected components %%%%%%%%%%%%%%%%%
%
if BOLD_COLORS==1
  mapcolors = 1:ntopos+1;
else
  mapcolors = [1 maporder+1];
end

if strcmpi(g.sumenv,'on')  || strcmpi(g.sumenv,'fill') %%%%%%%% if 'sunvenv' %%%%%%%%%
 sumenv = envelope(sumproj(:,:), g.envmode);
 if ~ylimset && max(sumenv(:)) > ymax, ymax = max(sumenv(1,:)); end
 if ~ylimset && min(sumenv(:)) < ymin, ymin = min(sumenv(2,:)); end
 if strcmpi(g.sumenv,'fill')
    %
    % Plot the summed projection filled
    %
    mins = matsel(sumenv,frames,0,2,0);
    p=fill([times times(frames:-1:1)],...
        [matsel(sumenv,frames,0,1,0) mins(frames:-1:1)],g.fillcolor);
    set(p,'EdgeColor',g.fillcolor);
    hold on
    %
    % Overplot the data envelope so it is not covered by the fill()'d component
    %
    p=plot(times,matsel(envdata,frames,0,1,1),colors(mapcolors(1),1));% plot the max
    set(p,'LineWidth',2);                % component order (if BOLD_COLORS==0)
    p=plot(times,matsel(envdata,frames,0,2,1),colors(mapcolors(1),1));% plot the min
    set(p,'LineWidth',2);                % component order (if BOLD_COLORS==0)

 else % if no 'fill'
     if ntopos ==1 && g.plotproj
         hold on; pproj = plot(times,sumproj);
         set(pproj,'Tag','line_allprojections');
     end
    tmp = matsel(sumenv,frames,0,2,0);
    p=plot(times,tmp);% plot the min
    hold on
    set(p,'color',g.fillcolor,'Tag','line_envelope_2');
    set(p,'linewidth',3);
    p=plot(times,matsel(sumenv,frames,0,1,0));% plot the max
    set(p,'linewidth',3);
    set(p,'color',g.fillcolor,'Tag','line_envelope_2');
 end

 set(p,'Tag','patch_envelope');
end

if strcmpi(g.sortvar,'rp')
	t = text(double(xmin+0.1*(xmax-xmin)), ...
         double(ymin+0.1*(ymax-ymin)), ...
         ['rp ' num2str(sumppaf,'%4.2f') '%']);
elseif strcmpi(g.sortvar,'pv')
    	t = text(double(xmin+0.1*(xmax-xmin)), ...
         double(ymin+0.1*(ymax-ymin)), ...
         ['pvaf ' num2str(sumppaf,'%4.2f') '%']);
else
	t = text(double(xmin+0.1*(xmax-xmin)), ...
         double(ymin+0.1*(ymax-ymin)), ...
         ['ppaf ' num2str(sumppaf,'%4.2f') '%']);
end
set(t,'fontsize',FONTSIZESMALL,'fontweight','bold','Tag','text_inaxes')

%
% %%%%%%%%%%%%%%%%%%%%%%%% Plot the computed component envelopes %%%%%%%%%%%%%%%%%%
%
    envx = [1;compx+1];
    for c = 1:ntopos+1
        curenv = matsel(envdata,frames,0,1,envx(c));
        if ~ylimset && max(curenv) > ymax, ymax = max(curenv); end
        p=plot(times,curenv,colors(mapcolors(c),1),'Tag',['line_envelope_' num2str(c)]);% plot the max
        set(gca,'FontSize',FONTSIZESMALL,'FontWeight','Bold')
        if c==1                                % Note: use colors in original
            set(p,'LineWidth',2);              %       component order (if BOLD_COLORS==0)
        else
            set(p,'LineWidth',1);
        end
        if all_bold > 0
                set(p,'LineStyle','-','LineWidth',3);
        elseif mapcolors(c)>15                            % thin/dot 16th-> comp. envs.
                set(p,'LineStyle',':','LineWidth',1);
        elseif mapcolors(c)>10                            %
                set(p,'LineStyle',':','LineWidth',2);
        elseif mapcolors(c)>6                             % dot 6th-> comp. envs.
                set(p,'LineStyle',':','LineWidth',3);
        elseif mapcolors(c)>1
            set(p,'LineStyle',colors(mapcolors(c),2),'LineWidth',1);
            if colors(mapcolors(c),2) == ':'
                set(l1,'LineWidth',2);  % embolden dotted env lines
            end
        end
        hold on
        curenv = matsel(envdata,frames,0,2,envx(c));
        if ~ylimset && min(curenv) < ymin, ymin = min(curenv); end
        p=plot(times,curenv,colors(mapcolors(c),1),'Tag',['line_envelope_' num2str(c)]);% plot the min

        if c==1
            set(p,'LineWidth',2);
        else
            set(p,'LineWidth',1);
        end
        if all_bold > 0
                set(p,'LineStyle','-','LineWidth',3);
        elseif mapcolors(c)>15                            % thin/dot 11th-> comp. envs.
                set(p,'LineStyle',':','LineWidth',1);
        elseif mapcolors(c)>10
                set(p,'LineStyle',':','LineWidth',2);
        elseif mapcolors(c)>6                             % dot 6th-> comp. envs.
                set(p,'LineStyle',':','LineWidth',3);
        elseif mapcolors(c)>1
            set(p,'LineStyle',colors(mapcolors(c),2),'LineWidth',1);
            if colors(mapcolors(c),2) == ':'
                set(l1,'LineWidth',2);  % embolden dotted env lines
            end
        end
        if c==1 && ~isempty(g.vert)
            for v=1:length(g.vert)
                vl=plot([g.vert(v) g.vert(v)], [-1e10 1e10],'k--','Tag','line_vertline'); % plot specified vertical lines
                if any(g.limcontrib ~= 0) && v>= length(g.vert)-1;
                    set(vl,'linewidth',g.limcontribweight);
                    set(vl,'linestyle',':');
                else
                    set(vl,'linewidth',g.vertweight);
                    set(vl,'linestyle','--');
                end
            end
        end
        if g.limits(1) <= 0 && g.limits(2) >= 0    % plot vertical line at time zero
                vl=plot([0 0], [-1e10 1e10],'k');
                    set(vl,'linewidth',2,'Tag','line_vertatzero');
        end

        %
        % plot the n-th component filled
        %
        if g.fillcomp(1)>0 && find(g.fillcomp==c-1)
            fprintf('filling the envelope of component %d\n',c-1);
            mins = matsel(envdata,frames,0,2,envx(c));
            p=fill([times times(frames:-1:1)],...
                   [matsel(envdata,frames,0,1,envx(c)) mins(frames:-1:1)],...
                   colors(mapcolors(c),1));
            %
            % Overplot the data envlope again so it is not covered by the fill()'d component
            %
            p=plot(times,matsel(envdata,frames,0,1,envx(1)),colors(mapcolors(1),1));% plot the max
            set(p,'LineWidth',2);                % component order (if BOLD_COLORS==0)
            p=plot(times,matsel(envdata,frames,0,2,envx(1)),colors(mapcolors(1),1));% plot the min
            set(p,'LineWidth',2);                % component order (if BOLD_COLORS==0)
        end
    end  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%
%%%%%%%%%%%%%%%%%%%%%%% Extend y limits by 5% %%%%%%%%%%%%%%%%%%%%%%%%%%
%
if ~ylimset
  datarange = ymax-ymin;
  ymin = ymin-0.05*datarange;
  ymax = ymax+0.05*datarange;
end
axis([pmin pmax ymin ymax]);

%
%%%%%%%%%%%%%%%%%%%%%% Label axes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
set(axe,'Color',axcolor);
if ~xunitframes
   l= xlabel('Time (s)');
else % xunitframes == 1
   l= xlabel('Data (time points)');
end
set(l,'FontSize',FONTSIZEMED,'FontWeight','Bold');
if strcmpi(g.envmode, 'avg')
    l=ylabel('Potential (\muV)');
else
    l=ylabel('RMS of \muV');
end;
set(l,'FontSize',FONTSIZEMED,'FontWeight','Bold');
%
%%%%%%%%%%%%%% Draw maps and oblique/vertical lines %%%%%%%%%%%%%%%%%%%%%
%
% axall = axes('Units','Normalized','Position',pos,...
axall = axes('Position',pos,...
    'Visible','Off','Fontsize',FONTSIZE); % whole-figure invisible axes
axes(axall)
set(axall,'Color',axcolor);
axis([0 1 0 1])

width  = xmax-xmin;
pwidth  = pmax-pmin;
height = ymax-ymin;

if strcmpi(g.dispmaps, 'on')
    for t=1:ntopos % draw oblique lines from max env vals (or plot top)
                 % to map bases, in left to right order
        %
        %%%%%%%%%%%%%%%%%%% draw oblique lines %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %
        if BOLD_COLORS==1
            linestyles = 1:ntopos;
        else
            linestyles = maporder;
        end
        axes(axall)
        axis([0 1 0 1]);
        set(axall,'Visible','off');
        maxenv = matsel(envdata,frames,plotframes(t),1,compx(t)+1);
        % max env val
        data_y = g.axisoff*(g.voffsets(t)+maxenv-ymin)/height;
        if (data_y > pos(2)+g.axisoff*pos(4))
            data_y = pos(2)+g.axisoff*pos(4);
        end
        l1 = plot([(plottimes(t)-pmin)/pwidth  ...
                   topoleft + 1/pos(3)*(t-1)*1.2*topowidth + (topowidth*g.axisoff)],...
                  [data_y (g.axisoff + 0.08)], ...
                  colors(linestyles(t)+1),'Tag',['line_topoconnect_' num2str(t)]); % 0.68 is bottom of topo maps
        if all_bold > 0
                set(l1,'LineStyle','-','LineWidth',3);
        elseif linestyles(t)>15                        % thin/dot 11th-> comp. envs.
                set(l1,'LineStyle',':','LineWidth',1);
        elseif linestyles(t)>10
                set(l1,'LineStyle',':','LineWidth',2);
        elseif linestyles(t)>5                     % dot 6th-> comp. envs.
                set(l1,'LineStyle',':','LineWidth',3);
        elseif linestyles(t)>1
            set(l1,'LineStyle',colors(linestyles(t)+1,2),'LineWidth',1);
            if colors(linestyles(t)+1,2) == ':'
                set(l1,'LineStyle',colors(linestyles(t)+1,2),'LineWidth',2);
            end
        end
        hold on
        %
        %%%%%%%%%%%%%%%%%%%% add specified vertical lines %%%%%%%%%%%%%%%%%%%%%%%%%
        %
        if g.voffsets(t) > 0
            l2 = plot([(plottimes(t)-xmin)/width  ...
                       (plottimes(t)-xmin)/width],...
                      [g.axisoff*(maxenv-ymin)/height ...
                       g.axisoff*(g.voffsets(t)+maxenv-ymin)/height],...
                      colors(linestyles(t)+1));
            if all_bold > 0
                    set(l2,'LineStyle','-','LineWidth',3);
            elseif linestyles(t)>15                      % thin/dot 11th-> comp. envs.
                    set(l2,'LineStyle',':','LineWidth',1);
            elseif linestyles(t)>10
                    set(l2,'LineStyle',':','LineWidth',2);
            elseif linestyles(t)>5                   % dot 6th-> comp. envs.
                    set(l2,'LineStyle',':','LineWidth',3);
            else
                set(l1,'LineStyle',colors(linestyles(t)+1,2),'LineWidth',1);
                if colors(linestyles(t)+1,2) == ':'
                    set(l1,'LineWidth',2);
                end
            end
        end
        set(gca,'Visible','off');
        axis([0 1 0 1]);
    end % t
end; % if g.dispmaps == on

%
%%%%%%%%%%%%%%%%%%%%%%%%% Plot the topoplots %%%%%%%%%%%%%%%%%%%%%%%%%%
%

if strcmpi(g.dispmaps, 'on')

    % common scale for colors
    % -----------------------
    if strcmpi(g.actscale, 'on')
        maxvolt = 0;
        for n=1:ntopos
            maxvolt = max(max(abs(maxproj(:,n))), maxvolt);
        end
    end

    [tmp tmpsort] = sort(maporder);
    [tmp tmpsort] = sort(tmpsort);

    for t=1:ntopos % left to right order  (maporder)
                   % axt = axes('Units','Normalized','Position',...
%         axt = axes('Units','Normalized','Position',...
%                    [pos(3)*topoleft+pos(1)+(t-1)*head_sep*topowidth pos(2)+0.66*pos(4) ...
%                     topowidth topowidth*head_sep]);
        axt = axes('Units','Normalized','Position',...
                   [pos(3)*topoleft+pos(1)+(t-1)*head_sep*topowidth  pos(2)+(g.axisoff+0.06)*pos(4) ...
                    topowidth topowidth*head_sep],...
                    'Tag',['axes_topo_' num2str(t)]);
        axes(axt)                             % topoplot axes
        cla

        if ~isempty(g.chanlocs)  % plot the component scalp maps
            if ~isempty(varargin)
                topoplot(maxproj(g.plotchans,t),g.chanlocs(g.plotchans), varargin{:});
            else  % if no varargin specified
                topoplot(maxproj(g.plotchans,t),g.chanlocs(g.plotchans),...
							'style','both','emarkersize',3);
            end
            axis square
            set(gca, 'userdata', ...
   ['text(-0.6, -0.6, ''' g.sortvar ': ' sprintf('%6.2f', sortvar(tmpsort(t))) ''');']);
        else
			axis off;
        end

        %
        %%%%%%%%%%%%% Scale colors %%%%%%%%%%%%%%%%%%%%%%%%%
        %
        if strcmpi(g.actscale, 'on')
            caxis([-maxvolt maxvolt]);
        end
        %
        %%%%%%%%%%%%%%%%%%%%%%%% label components %%%%%%%%%%%%%%%%%%%%%%%
        %
        if t==1
            chid = fopen('envtopo.labels','r');
            if chid <3,
                numlabels = 1;
            else
                fprintf('Will label scalp maps with labels from file %s\n',...
					'envtopo.labels');
                compnames = fscanf(chid,'%s',[4 MAXPLOTDATACHANS]);
                compnames = compnames';
                [r c] = size(compnames);
                for i=1:r
                    for j=1:c
                        if compnames(i,j)=='.',
                            compnames(i,j)=' ';
                        end
                    end
                end
                numlabels=0;
            end
        end
        if numlabels == 1
            complabel = int2str(maporder(t));        % label comp. numbers
        else
            complabel = compnames(t,:);              % use labels in file
        end
        text(0.00,0.80,['IC ' complabel],'FontSize',FONTSIZEMED,...
             'FontWeight','Bold','HorizontalAlignment','Center');
        % axt = axes('Units','Normalized','Position',[0 0 1 1],...
        axt = axes('Position',[0 0 1 1],...
                   'Visible','Off','Fontsize',FONTSIZE);
        set(axt,'Color',axcolor);           % topoplot axes
        drawnow
    end
    %
    %%%%%%%%%%%%%%%%%%%%%%%%%%% Plot a colorbar %%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    % axt = axes('Units','Normalized','Position',[.88 .58 .03 .10]);
%     axt = axes('Position',[pos(1)+pos(3)*1.015 pos(2)+0.6055*pos(4) ...
% 				pos(3)*.02 pos(4)*0.09]);
   axt = axes('Position',[pos(1)+pos(3)*1.015 pos(2)+(g.axisoff)*pos(4) ...
				pos(3)*.02 pos(4)*0.09]);
    if strcmpi(g.actscale, 'on')
        h=cbar(axt, [1:64],[-maxvolt maxvolt],3);
    else
        h=cbar(axt);                        % colorbar axes
        set(h,'Ytick',[]);

        axes(axall)
        set(axall,'Color',axcolor);
        tmp = text(0.50,1.05,g.title,'FontSize',FONTSIZE,...
						'HorizontalAlignment','Center',...
						'FontWeight','Bold');
        set(tmp, 'interpreter', 'none');
%         text(1,0.68,'+','FontSize',FONTSIZE,'HorizontalAlignment','Center');
        text(1,g.axisoff+0.08,'+','FontSize',FONTSIZE,'HorizontalAlignment','Center');
        % text(1,0.637,'0','FontSize',12,'HorizontalAlignment','Center',...
		%	'verticalalignment','middle');
%         text(1,0.61,'-','FontSize',FONTSIZE,'HorizontalAlignment','Center');
        text(1,g.axisoff+0.01,'-','FontSize',FONTSIZE,'HorizontalAlignment','Center');
    end
    axes(axall)
    set(axall,'layer','top'); % bring component lines to top

end
%
%%%%%%%%%%%%%%%%%%%%%%%%% turn on axcopy %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
axcopy(gcf, ...
  'if ~isempty(get(gca,''''userdata'''')), eval(get(gca,''''userdata''''));end;');

return %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function envdata = envelope(data, envmode)  % also in release as env()
  if nargin < 2
      envmode = 'avg';
  end
  if strcmpi(envmode, 'rms'); % return rms of pos and neg vals at each time point
      warning off;
      datnaeg = (data < 0).*data; % zero out positive values
      dataneg = -sqrt(sum(dataneg.^2,1) ./ sum(negflag,1));

      datapos = (data > 0).*data; % zero out negative values
      datapos = sqrt(sum(datapos.^2,1) ./ sum(posflag,1));

      envdata = [datapos;dataneg];
      warning on;
  else  % find max and min value at each time point
      if size(data,1)>1
          maxdata = max(data); % max at each time point
          mindata = min(data); % min at each time point
          envdata = [maxdata;mindata];
      else
          maxdata = max([data;data]); % max at each time point
          mindata = min([data;data]); % min at each time point
          envdata = [maxdata;mindata];
      end
  end

return %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


function rtk=udstate_rtkins(rtk,obsr,obsb,nav,ind)

global glc
tt=rtk.tt;

% update the position/velocity/attitude
rtk=udpos_rtkins(rtk,tt);

% update ionosphereic parameter
if rtk.opt.ionoopt==glc.IONOOPT_EST
    roverpos=blh2xyz(rtk.x(7:9))';
    bl=norm(roverpos-rtk.basepos);
    rtk=udion_rtkins(rtk,tt,bl,ind);
end

% update tropspheric parameter
if rtk.opt.tropopt>=glc.TROPOPT_EST
    rtk=udtrop_rtkins(rtk,tt,bl);
end

% update reciever inter-frequency bias for glonass
if rtk.opt.glomodear==2&&rtk.mask(2)==1
    rtk=udrcvbias_rtkins(rtk,tt);
end

% update the ambiguity
if rtk.opt.mode>glc.PMODE_DGNSS
    rtk=udbias_rtkins(rtk,obsr,obsb,nav,ind);
end

return


function p = presolve(p)

model = p.model;

p.model.Q = p.model.Q*0;
p.model.F_struc(1:p.dimin(1),:)=[];
p.model.K.f = p.model.K.f-p.dimin(1);
redundant = sparse(zeros(p.model.K.l,1));
for i = 1:p.model.K.l
    b = p.model.F_struc(p.model.K.f+i,1);
    p.model.F_struc(p.model.K.f+i,1) = b+1;
    p.model.c = p.model.F_struc(p.model.K.f+i,2:end)';

     eval(['output = ' p.model.solver.call '(p.model);']);
     if output.problem == 0
         if p.model.c'*output.Primal > -b
             redundant(i) = 1
         end
     end

     p.model.F_struc(p.model.K.f+i,1) = b;
end
p.model.c = c;
p.model.Q = c;


% ------------------------------------------------------------------------
%  Copyright (C)
%  Universitat Politecnica de Catalunya BarcelonaTech (UPC) - Spain
%  University of California Berkeley (UCB) - USA
%
%  Jordi Pont-Tuset <jordi.pont@upc.edu>
%  Pablo Arbelaez <arbelaez@berkeley.edu>
%  June 2014
% ------------------------------------------------------------------------
% This file is part of the MCG package presented in:
%    Arbelaez P, Pont-Tuset J, Barron J, Marques F, Malik J,
%    "Multiscale Combinatorial Grouping,"
%    Computer Vision and Pattern Recognition (CVPR) 2014.
% Please consider citing the paper if you use this code.
% ------------------------------------------------------------------------
function [ucm2, ucms, elapsed_time] = contours_to_ucm(I, scales, E, O, all_parameters, param_multi, align_thr)
  % function [ucm2, ucms, elapsed_time] = contours_to_ucm(I, scales, E, O, all_parameters, param_multi, align_thr)
  % Multiscale hierarchical segmentation on RGBD images
  % Pablo Arbelaez
  % arbelaez@berkeley.edu

  if nargin<5,
    all_parameters = [5 60 4 2 0.1];
    % all_parameters = [3.3 60 4 2 0.1];
    % all_parameters = [30 60 4 2 0.09]; % NYUD2 train parameters
  end
  if nargin<6,
      param_multi.weights      = [0.7 1 1.3];
  end
  if nargin<7,
      align_thr = 0.13;
  end

  param.mult_Pb   = all_parameters(1);
  param.sat_sPb   = all_parameters(2);
  param.nvec      = all_parameters(3);
  param.dthresh   = all_parameters(4);
  param.ic_gamma  = all_parameters(5);

  [param.tx, param.ty, ~] = size(I);

  % compute ucms at multiple scales
  ucms = cell(numel(scales),1);
  elapsed_time = zeros(11,1);
  for s = 1:numel(scales),
      param.scale = scales(s);
      [ucms{s}, times] = img2ucm_scale(E{s}, O{s}, param);
      elapsed_time(3*(s-1)+1:3*s)=times;
  end

  % align ucms
  T=tic;
  ucms = project_ucms_wrap(ucms, align_thr);
  elapsed_time(10)=toc(T);

  % combine ucms
  T=tic;
  ucm2 = ucms2multi(ucms, param_multi);
  elapsed_time(11)=toc(T);

%%
function [ucm2, times] = img2ucm_scale(E, O, param)
  % compute hierarchical segmentation at each scale independently
  % I = imresize(I, param.scale, 'lanczos3');
  [ucm2, times] = img2ucm(E, O, param.mult_Pb, param.sat_sPb, param.nvec, param.dthresh, param.ic_gamma);

  % resample ucm to original image size
  T=tic;
  if ~isequal([param.tx, param.ty], size(ucm2(3:2:end, 3:2:end))),
      % TODO: Instead of resampling for each threshold, resample leaves and redo mergings
      ucm2 = resample_ucm2(ucm2, [param.tx, param.ty]);
  end
  times(3)=toc(T);

%%
function [ucm2, times] = img2ucm(E, O, mult_Pb, sat_sPb, nvec, dthresh, ic_gamma)

  % edge detection
  T=tic;
  % SAURABH: plug the rgbd contours here
  % [E,~,O] = edgesDetect( I, model );
  times(1)=toc(T);

  % continuous oriented watershed transform
  T=tic;
  [owt2, superpixels] = contours2OWT(E, O);

  % globalization
  [ sPb_thin] = spectralPb_fast(owt2 * mult_Pb, nvec, ic_gamma, dthresh) / sat_sPb;

  % ultrametric contour map with mean pb.
  ucm2 = double(ucm_mean_pb( (owt2 + sPb_thin), superpixels) );
  times(2)=toc(T);

%%
function ucm2 = ucms2multi(all_ucms, param)

  %combine ucms
  weights = param.weights;
  weights = weights ./ sum(weights);

  sz = size(all_ucms);
  W_all = repmat(repmat(weights', [1,sz(2)]),[1,1,sz(1)]); W_all = permute(W_all, [3 2 1]);
  all_ucms = all_ucms.*W_all;

  ucm2_wt = sum(all_ucms,3);

  labels2 = bwlabel(ucm2_wt == 0, 8);
  labels = labels2(2:2:end, 2:2:end) - 1; % labels begin at 0 in mex file.
  ucm2 = double(ucm_mean_pb(ucm2_wt, labels));
  % bw = (ucm2==0);
  % ucm2 = apply_sigmoid(ucm2, param.thr, param.fq);
  % ucm2(bw) = 0;


function mov = rmPlotGUI_predictionMovie(M, aviFile, fps);
% Animate a movie of the stimulus sweeping across the pRF, and the
% predicted response, for the selected voxel in the rm Plot GUI.
%
%  mov = rmPlotGUI_predictionMovie([M], [aviFile], [fps=6]);
%
% INPUTS:
%	M: rmPlotGUI struct. [default: get from cur fig]
%
%	aviFile: optional .avi file to save the movie. [if not path provided,
%	won't save an .avi file.]
%
%	fps: frames per second for the avi movie (default: 6)
%
% OUTPUTS:
%	mov: movie structure. See GETFRAME.
%
% ras, 05/2009.
if notDefined('M'),		M = get(gcf, 'UserData');			end
if notDefined('aviFile'),	aviFile = '';					end
if notDefined('fps'),		fps = 6;						end

%% get the prediction for this voxel
v = get(M.ui.voxel.sliderHandle, 'Value');
coords = M.coords(:,v);
if isequal(M.roi.viewType, 'Gray')  % convert coords into an index
    coords = M.coords(v);
end
[pred RF rfParams variance_explained] = rmPlotGUI_makePrediction(M, coords);

%% create the animation, get the frames
nFrames = size(M.tSeries, 1);

for n = 1:nFrames
	%% plot the time series up to this frame
	axes(M.ui.tsAxes); cla; hold on;

    % We can either plot a static time series and growing prediction...
    % 	hTSeries = plot(M.x, M.tSeries(:,v), 'k--', 'LineWidth', 1.5);
    % 	hFit = plot(M.x(1:n), pred(1:n,1), 'b', 'LineWidth', 2);

    % Or a static prediction and a growing time series (my preference - jw)
    hTSeries = plot(M.x, M.tSeries(:,v), 'k--', 'LineWidth', 1.5);
	hFit = plot(M.x(1:n), pred(1:n,1), 'b', 'LineWidth', 2);

    % Don't plot the residual - too much clutter (jw)
    % 	hResidual = plot(M.x(1:n), M.tSeries(1:n,v)-pred(:,1), 'r:', 'LineWidth', 1);

	allPlotted = [M.tSeries(:,v); pred(:,1); M.tSeries(:,v)-pred(:,1)];
	axis([min(M.x) max(M.x) min(allPlotted) max(allPlotted)]);
	h = axis;
% 	for n=1:numel(M.sepx),
% 		plot([1 1].*M.sepx(n), [h(3) h(4)], 'k:', 'LineWidth', 2);
% 	end;
	xlabel('Time (sec)');
	ylabel('BOLD signal change (%)');

	%% show the stimulus position over the pRF for this frame
	TR = M.params.stim(1).framePeriod;  % TODO: deal w/ diff't TRs in diff't scans
	t = get(M.ui.time.sliderHandle, 'Value') * TR;

	% get the stimulus image for this frame
	[stimImage RFresampled] = getCurStimImage(M, n, RF);

	% overlay and display
	axes(M.ui.rfAxes); cla
% 	RF_img(:,:,1) = RF;
% 	RF_img(:,:,2) = 1-RF;
% 	RF_img(:,:,3) = stimImage;
	RF_img(:,:,1) = stimImage;
	RF_img(:,:,2) = RFresampled;
	RF_img(:,:,3) = RFresampled;

    [x,y] = prfSamplingGrid(M.params);
    x = x(:); y = y(:);
    imagesc(x, -y, RF_img); hold on;
    plot([min(x) max(x)], [0 0], 'k-');
    plot( [0 0], [min(y) max(y)], 'k-');

    axis image  xy;
    ylabel('y (deg)');
    xlabel('x (deg)');

	%% grab the current movie frame
	mov(n) = getframe(gcf);
end

%% save the .avi file, if a path is provided.
if ~isempty(aviFile)
	quality = 100;
	description = aviFile;
	keyframe = fps;
	if ispc
		compression = 'Indeo5';
	else
		compression = 'None';
	end

	ensureDirExists( fileparts(aviFile) );

	movie2avi(mov, aviFile, 'FPS', fps, 'Compression', compression, ...
		  'Quality', quality, 'Videoname', description, 'Keyframe', keyframe);
	fprintf('[%s]: Saved movie as %s.\n', mfilename, aviFile);

end

return
%--------------------------------------

%--------------------------------------
function [stimImage RF] = getCurStimImage(M, f, RFvals)
% Get a stimulus image matching the sampling positions as the RF.
% Also returns the RF resampled into a square grid.
x = prfSamplingGrid(M.params);

% account for the different stimuli that are shown next to each other
% f originally refers to the frame in the combined time series across scans:
% we want to break this down into scan n, frame f within that scan.
n = 1;
nStimScans = numel(M.params.stim);
while n <= nStimScans,
    tmp = f + M.params.stim(n).prescanDuration;
    if tmp > size(M.params.stim(n).images_org,2),
        f = tmp - size(M.params.stim(n).images_org,2);
        n = n + 1;
    else
        f = tmp;
        break;
    end
end

% stim image
stimImage     = NaN(size(x));
stimImage(M.params.stim(1).instimwindow) = M.params.stim(n).images_org(:,f);
stimImage     = reshape(stimImage, size(x));

% RF
RF     = NaN(size(x));
RF(M.params.stim(1).instimwindow) = normalize(RFvals, 0, 1);
RF     = reshape(RF, size(x));

return


function Fcell = get_signals(ops, iplane)

try
   load(sprintf('%s/F_%s_%s_plane%d_Nk%d.mat',...
       ops.ResultsSavePath,ops.mouse_name, ops.date, iplane, ops.Nk))
catch
   error('Could not find cell detection file \n')
end

Nk = numel(stat);
Nkpar = ops.Nk;

%% get signals
[Ly Lx] = size(ops.mimg);

nimgbatch = 2000;

ix = 0;
fclose all;
fid = fopen(ops.RegFile, 'r');

tic
F = zeros(Nk, sum(ops.Nframes), 'single');
while 1
    data = fread(fid,  Ly*Lx*nimgbatch, '*int16');
    if isempty(data)
       break;
    end
    data = reshape(data, Ly, Lx, []);
    data = data(ops.yrange, ops.xrange, :);
    data = single(data);
    NT= size(data,3);

    data = single(reshape(data, [], NT));

    for k = 1:Nk
       ipix = stat(k).ipix;
       if ~isempty(ipix)
%            F(k,ix + (1:NT)) = stat(k).lambda' * data(ipix,:);
            F(k,ix + (1:NT)) = mean(data(ipix,:), 1);
       end
    end

    ix = ix + NT;
    if rem(ix, 3*NT)==0
        fprintf('Frame %d done in time %2.2f \n', ix, toc)
    end
end
fclose(fid);
% F = F(:, 1:ix);

csumNframes = [0 cumsum(ops.Nframes)];
Fcell = cell(1, length(ops.Nframes));
for i = 1:length(ops.Nframes)
    Fcell{i} = F(:, csumNframes(i) + (1:ops.Nframes(i)));
end

save(sprintf('%s/F_%s_%s_plane%d_Nk%d.mat', ops.ResultsSavePath, ...
    ops.mouse_name, ops.date, iplane, ops.Nk),  'ops', 'res', 'stat', 'stat0', 'res0', 'Fcell', 'clustrules')


function [tc,relres,iter,xrec] = gablasso(x,g,a,M,lambda,varargin)
%GABLASSO  LASSO regression in Gabor domain
%   Usage: [tc,xrec] = gablasso(x,a,M,lambda,C,tol,maxit)
%
%   `gablasso` has been deprecated. Please use |franalasso| instead.
%
%   A call to `gablasso(x,g,a,M,lambda)` can be replaced by ::
%
%     F=frame('dgt',[],g,a,M);
%     tc=franalasso(F,lambda);
%
%   Any additional parameters passed to `gablasso` can be passed to
%   |franalasso| in the same manner.
%
%   See also: frame, franalasso

warning(['LTFAT: GABLASSO has been deprecated, please use FRANALASSO ' ...
         'instead. See the help on GABLASSO for more details.']);

F=newframe('dgt',[],g,a,M);
[tc,relres,iter,xrec] = franalasso(F,lambda,varargin{:});


function [curv] = mne_read_curvature(fname)
%
% [curf] = mne_read_surface(fname)
%
% Reads a FreeSurfer curvature file
%
% fname       - The file to read
% curv        - The curvature values
%

%
%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
%
%   Revision 1.4  2006/07/31 05:12:39  msh
%   fread3 was still called instead of mne_fread3
%
%   Revision 1.3  2006/05/22 11:01:47  msh
%   Deleted superfluous text from the comments.
%
%   Revision 1.2  2006/05/22 10:55:02  msh
%   Fixed help text.
%
%   Revision 1.1  2006/05/22 10:44:44  msh
%   Added surface and curvature reading routines.
%   Fixed error in mne_read_source_spaces: triangle normals were not normalized
%

me='MNE:mne_read_curvature';

%
%   The input file is big endian
%
fid = fopen(fname,'rb','ieee-be');

if (fid < 0)
   error(me,'Cannot open file %s', fname);
end;

magic = mne_fread3(fid) ;
NEW_VERSION_MAGIC_NUMBER = 16777215;
if (magic == NEW_VERSION_MAGIC_NUMBER)
    nvert = fread(fid, 1, 'int32');
    nface = fread(fid, 1, 'int32');
    val_per_vertex = fread(fid, 1, 'int32');
    if val_per_vertex ~= 1
        fclose(fid);
        error(me,'Values per vertex not equal to one');
    end
    curv = fread(fid, nvert, 'float') ;
    fprintf(1,'\t%d values read from a new style curvature file.\n',nvert);
else
    nvert = magic;
    nface = mne_fread3(fid);
    curv = fread(fid, nvert, 'int16') ./ 100 ;
    fprintf(1,'\t%d values read from an old style curvature file.\n',nvert);
end

fclose(fid);

return;


%SerialLink.fkine Forward kinematics
%
% T = R.fkine(Q, OPTIONS) is the pose of the robot end-effector as an SE(3)
% homogeneous transformation (4x4) for the joint configuration Q (1xN).
%
% If Q is a matrix (KxN) the rows are interpreted as the generalized joint
% coordinates for a sequence of points along a trajectory.  Q(i,j) is the
% j'th joint parameter for the i'th trajectory point.  In this case T is a
% 3d matrix (4x4xK) where the last subscript is the index along the path.
%
% [T,ALL] = R.fkine(Q) as above but ALL (4x4xN) is the pose of the link
% frames 1 to N, such that ALL(:,:,k) is the pose of link frame k.
%
% Options::
%  'deg'    Assume that revolute joint coordinates are in degrees not
%           radians
%
% Note::
% - The robot's base or tool transform, if present, are incorporated into the
%   result.
% - Joint offsets, if defined, are added to Q before the forward kinematics are
%   computed.
%
% See also SerialLink.ikine, SerialLink.ikine6s.

% Copyright (C) 1993-2015, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

function [t allt] = fkine(robot, q, varargin)

%
% evaluate fkine for each point on a trajectory of
% theta_i or q_i data
%

n = robot.n;

opt.deg = false;

opt = tb_optparse(opt, varargin);

if opt.deg
    % in degrees mode, scale the columns corresponding to revolute axes
    k = ~robot.links.isprismatic;
    q(:,k) = q(:,k) * pi/180;
end

if nargout > 1
    allt = zeros(4,4,n);
    if isa(q,'sym')
        allt = sym(allt);
    end
end

L = robot.links;
if numel(q) == n
    t = robot.base;
    for i=1:n
        t = t * L(i).A(q(i));

        if nargout > 1
            allt(:,:,i) = t; % intermediate transformations
        end
    end
    t = t * robot.tool;
else
    if numcols(q) ~= n
        error('q must have %d columns', n)
    end
    t = zeros(4,4,0);
    for qv=q',		% for each trajectory point
        tt = robot.base;
        for i=1:n
            tt = tt * L(i).A(qv(i));
        end
        t = cat(3, t, tt * robot.tool);
    end
end

if isa(t, 'sym')
    t = simplify(t);
end

%robot.T = t;
%robot.notify('Moved');


function [marginal, msg, loglik] = filter_evidence_old(engine, evidence)
% [marginal, msg, loglik] = filter_evidence(engine, evidence) (pearl_dbn)

[ss T] = size(evidence);
bnet = bnet_from_engine(engine);
bnet2 = dbn_to_bnet(bnet, T);
ns = bnet2.node_sizes;
hnodes = mysetdiff(1:ss, engine.onodes);
hnodes = hnodes(:)';

[engine.parent_index, engine.child_index] = mk_pearl_msg_indices(bnet2);

msg = init_msgs(bnet2.dag, ns, evidence);
msg = init_ev_msgs(engine, evidence, msg);

verbose = 1;
if verbose, fprintf('\nold filtering\n'); end

for t=1:T
  % update pi
  for i=hnodes
    n = i + (t-1)*ss;
    ps = parents(bnet2.dag, n);
    if t==1
      e = bnet.equiv_class(i,1);
    else
      e = bnet.equiv_class(i,2);
    end
    msg{n}.pi = compute_pi(bnet.CPD{e}, n, ps, msg);
    %if verbose, fprintf('%d computes pi\n', n); disp(msg{n}.pi); end
    msg{n}.pi = normalise(msg{n}.pi(:) .* msg{n}.lambda_from_self(:));
    if verbose, fprintf('%d recomputes pi\n', n); disp(msg{n}.pi); end
  end
  % send pi msg to children
  for i=hnodes
    n = i + (t-1)*ss;
    cs = children(bnet2.dag, n);
    for c=cs(:)'
      j = engine.parent_index{c}(n); % n is c's j'th parent
      pi_msg = normalise(compute_pi_msg(n, cs, msg, c, ns));
      msg{c}.pi_from_parent{j} = pi_msg;
      if verbose, fprintf('%d sends pi to %d\n', n,c); disp(pi_msg); end
    end
  end
end

marginal = cell(ss,T);
lik = zeros(1,ss*T);
for t=1:T
  for i=1:ss
    n = i + (t-1)*ss;
    %[bel, lik(n)] = normalise(msg{n}.pi .* msg{n}.lambda);
    [bel, lik(n)] = normalise(msg{n}.pi);
    marginal{i,t} = bel;
  end
end

loglik = sum(log(lik));

%%%%%%%

function lambda = compute_lambda(n, cs, msg, ns)
% Pearl p183 eq 4.50
lambda = prod_lambda_msgs(n, cs, msg, ns);

%%%%%%%

function pi_msg = compute_pi_msg(n, cs, msg, c, ns)
% Pearl p183 eq 4.53 and 4.51
pi_msg = msg{n}.pi .* prod_lambda_msgs(n, cs, msg, ns, c);

%%%%%%%%%

function lam = prod_lambda_msgs(n, cs, msg, ns, except)

if nargin < 5, except = -1; end

%lam = msg{n}.lambda_from_self(:);
lam = ones(ns(n), 1);
for i=1:length(cs)
  c = cs(i);
  if c ~= except
    lam = lam .* msg{n}.lambda_from_child{i};
  end
end

%%%%%%%%%%%

function msg = init_msgs(dag, ns, evidence)
% INIT_MSGS Initialize the lambda/pi message and state vectors (pearl_dbn)
% msg =  init_msgs(dag, ns, evidence)
%
% We assume all the hidden nodes are discrete.

N = length(dag);
msg = cell(1,N);
observed = ~isemptycell(evidence(:));

for n=1:N
  ps = parents(dag, n);
  msg{n}.pi_from_parent = cell(1, length(ps));
  for i=1:length(ps)
    p = ps(i);
    msg{n}.pi_from_parent{i} = ones(ns(p), 1);
  end

  cs = children(dag, n);
  msg{n}.lambda_from_child = cell(1, length(cs));
  for i=1:length(cs)
    c = cs(i);
    msg{n}.lambda_from_child{i} = ones(ns(n), 1);
  end

  msg{n}.lambda = ones(ns(n), 1);
  msg{n}.pi = ones(ns(n), 1);

  msg{n}.lambda_from_self = ones(ns(n), 1);
end

%%%%%%%%%

function msg = init_ev_msgs(engine, evidence, msg)
% Initialize the lambdas with any evidence

[ss T] = size(evidence);
bnet = bnet_from_engine(engine);
pot_type = 'd';
t = 1;
hnodes = mysetdiff(1:ss, engine.onodes);
for i=hnodes(:)'
  c = engine.obschild(i);
  if c > 0
    fam = family(bnet.dag, c);
    e = bnet.equiv_class(c, 1);
    CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
    temp = pot_to_marginal(CPDpot);
    n = i;
    msg{n}.lambda_from_self = temp.T;
  end
end
for t=2:T
  for i=hnodes(:)'
    c = engine.obschild(i);
    if c > 0
      fam = family(bnet.dag, c, 2);
      e = bnet.equiv_class(c, 2);
      CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
      temp = pot_to_marginal(CPDpot);
      n = i + (t-1)*ss;
      msg{n}.lambda_from_self = temp.T;
    end
  end
end


classdef Zmap3DGridFunction < ZmapGridFunction
    % ZMAP3DGRIDFUNCTION is a ZmapFunction that produces a grid of volumetric results
    %
    % see also ZMAPGRIDFUNCTION

    properties
        features={'borders'}; % features to show on the map, such as 'borders','lakes','coast',etc.
    end
    properties(Constant)
        Type = GridTypes.XYZ;
    end

    methods

        function obj=Zmap3DGridFunction(varargin)
            unimplemented_error()
            obj@ZmapGridFunction(varargin{:});
        end

        function plot(obj,choice, varargin)
            % plots the results on the provided axes.
            if ~exist('choice','var')
                choice=obj.active_col;
            end
            if ~isnumeric(choice)
                choice = find(strcmp(obj.Result.values.Properties.VariableNames,choice));
            end

            mydesc = obj.Result.values.Properties.VariableDescriptions{choice};
            myname = obj.Result.values.Properties.VariableNames{choice};

            f=findobj(groot,'Tag',obj.PlotTag,'-and','Type','figure');
            if isempty(f)
                f=figure('Tag',obj.PlotTag);
            end
            figure(f);
            set(f,'name',['results from bvalgrid : ', myname])
            delete(findobj(f,'Type','axes'));

            % this is to show the data
            obj.Grid.pcolor([],obj.Result.values.(myname), mydesc);
            set(gca,'NextPlot','add');

            % the imagesc exists is to enable data cursor browsing.
            obj.plot_image_for_cursor_browsing(myname, mydesc, choice);

            shading(obj.ZG.shading_style);
            set(gca,'NextPlot','add')

            obj.add_grid_centers();

            ax=gca;
            for n=1:numel(obj.features)
                ft=obj.ZG.features(obj.features{n});
                copyobj(ft,ax);
            end

            colorbar
            title(mydesc)
            xlabel('Longitude')
            ylabel('Latitude')

            dcm_obj=datacursormode(gcf);
            dcm_obj.Updatefcn=@ZmapGridFunction.mydatacursor;
            if isempty(findobj(gcf,'Tag','lookmenu'))
                add_menu_divider();
                lookmenu=uimenu(gcf,'label','graphics','Tag','lookmenu');
                shademenu=uimenu(lookmenu,'Label','shading','Tag','shading');

                % TODO: combine mapdata_viewer with this function
                exploremenu=uimenu(gcf,'label','explore');
                uimenu(exploremenu,'label','explore'    , 'MenuSelectedFcn',@(~,~)mapdata_viewer(obj.Result,obj.RawCatalog,gcf));

                uimenu(shademenu,'Label','interpolated' , 'MenuSelectedFcn',@(~,~)shading('interp'));
                uimenu(shademenu,'Label','flat'         , 'MenuSelectedFcn',@(~,~)shading('flat'));

                plottype=uimenu(lookmenu,'Label','plot type');
                uimenu(plottype,'Label','Pcolor plot','Tag','plot_pcolor',...
                    'MenuSelectedFcn',@(src,~)obj.plot(choice),'Checked','on');

                % countour-related menu items

                uimenu(plottype,'Label','Plot Contours','Tag','plot_contour',...
                    'Enable','off',...not fully unimplmented
                    'MenuSelectedFcn',@(src,~)obj.contour(choice));
                uimenu(plottype,'Label','Plot filled Contours','Tag','plot_contourf',...
                    'Enable','off',...not fully unimplmented
                    'MenuSelectedFcn',@(src,~)contourf(choice));
                uimenu(lookmenu,'Label','change contour interval',...
                    'Enable','off',...
                    'MenuSelectedFcn',@(src,~)changecontours());

                % display overlay menu items

                uimenu(lookmenu,'Label','Show grid centerpoints','Checked',char(obj.showgridcenters),...
                    'MenuSelectedFcn',@obj.togglegrid_cb);
                uimenu(lookmenu,'Label',['Show ', obj.RawCatalog.Name, ' events'],...
                    'MenuSelectedFcn',@(src,~)obj.addquakes_cb(src,obj.RawCatalog));

                uimenu(lookmenu,'Separator','on',...
                    'Label','brighten',...
                    'MenuSelectedFcn',@(~,~)colormap(ax,brighten(colormap,0.4)));
                uimenu(lookmenu,'Label','darken',...
                    'MenuSelectedFcn',@(~,~)colormap(ax,brighten(colormap,-0.4)));

            end

            update_layermenu(obj,myname);
        end % plot function

    end % Public methods

    methods(Access=protected)
        function plot_image_for_cursor_browsing(obj, myname, mydesc, choice)
            h=obj.Grid.imagesc([],obj.Result.values.(myname));
            h.AlphaData=zeros(size(h.AlphaData))+0.0;

            % add some details that can be picked up by the interactive data cursor
            h.UserData.vals= obj.Result.values;
            h.UserData.choice=choice;
            h.UserData.myname=myname;
            h.UserData.myunit=obj.Result.values.Properties.VariableUnits{choice};
            h.UserData.mydesc=obj.Result.values.Properties.VariableDescriptions{choice};
        end

        function update_layermenu(obj, myname)
            if isempty(findobj(gcf,'Tag','layermenu'))
                layermenu=uimenu(gcf,'Label','layer','Tag','layermenu');
                for i=1:width(obj.Result.values)
                    tmpdesc=obj.Result.values.Properties.VariableDescriptions{i};
                    tmpname=obj.Result.values.Properties.VariableNames{i};
                    uimenu(layermenu,'Label',tmpdesc,'Tag',tmpname,...
                        'Enable',tf2onoff(~all(isnan(obj.Result.values.(tmpname)))),...
                        'MenuSelectedFcn',@(~,~)plot_cb(tmpname));
                end
            end

            % make sure the correct option is checked
            layermenu=findobj(gcf,'Tag','layermenu');
            set(findobj(layermenu,'Tag',myname),'Checked','on');

            % plot here
            function plot_cb(name)
                set(findobj(layermenu,'type','uimenu'),'Checked','off');
                obj.plot(name);
            end
        end

    end % Protected methods
    methods(Access=protected, Static)
        function addquakes_cb(src, catalog)
            qtag=findobj(gcf,'tag','quakes');
            if isempty(qtag)
                set(gca,'NextPlot','add')
                plot(catalog.X, catalog.Y, 'o',...
                    'MarkerSize',3,...
                    'markeredgecolor',[.2 .2 .2],...
                    'tag','quakes');
                set(gca,'NextPlot','replace')
            else
                ison=qtag.Visible == "on";
                qtag.Visible=tf2onoff(~ison);
                src.Checked=tf2onoff(~ison);
                drawnow
            end
        end
    end
end


%% This file will be used to plot the different simulation data
% Coded By: K
% Last Updated: 2019/06/23
%%
clc;clear all; close all;

%% Add path
addpath('./Datas')

%% Load data
load('SimulationData_V_1.mat')

%% Plot
close all
% figure(1)
% waterfall(x,tspan,real(u))
% colormap([0 0 0]);
% view(42,55)
% set(gca,'FontSize',18);
% set(gcf,'Position',[100 100 600 400]);
% set(gcf,'PaperPositionMode','auto');
% grid on

figure(2)
Spacer1=10;
Spacer2=15;
h1=surf(x,tspan,real(u))
set(h1,'LineStyle','none')
view(42,55)
set(gca,'FontSize',40);
set(gcf,'Position',[100 100 600 400]);
set(gcf,'PaperPositionMode','auto');
grid on

hold on
h2=surf(x(1:Spacer1:end),tspan(1:Spacer2:end),real(u(1:Spacer2:length(tspan),1:Spacer1:length(x))))
set(h2,'LineStyle','-')

% figure(3)
% pcolor(x,tspan,real(u))
% shading interp
% set(gca,'FontSize',18);
% set(gcf,'Position',[100 100 600 400]);
% set(gcf,'PaperPositionMode','auto');
% grid on


function colorSegmentation ( )

%% COLORSEGMENTATION segments the "fabric.jpg" image by color.
%
%    COLORSEGMENTATION displays a figure for each of the four segmented
%    colors: red, yellow, green, and magenta.
%
%  This function requires the Image Processing Toolbox.
%

%
%  Create a cell array of color names.
%
  colors = { 'red', 'yellow', 'green', 'magenta' };
%
%  Read the image.
%
  image = imread ( 'fabric.png' );

  imagesc ( image )
  title ( 'Original image to be color-filtered' )

  for index = 1: 4
%
% Each iteration will filter a different color
%
    filteredImage = colorFilter ( image, colors{index} );
%
%  Display the extracted segment.
%
    figure;
    imagesc ( filteredImage );
    title_string = sprintf ( 'Image filtered by %s', colors{index} );
    title ( title_string )

  end

  return
end


% visualize - Visualize
% Copyright (C) 2011 KyungHyun Cho, Tapani Raiko, Alexander Ilin
% Original code written by Tapani Raiko
%
% This program 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 2
% of the License, or (at your option) any later version.
%
% This program 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 this program; if not, write to the Free Software
% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
%
function visualize(W, horiz, do_sort, borders)
if (nargin < 2)
    horiz = 0;
end

if (nargin < 3)
    do_sort = 0;
end

if (do_sort == 1)
    Wnorms = sum(W.^2,1);
    [B,IX] = sort(Wnorms,'descend');
    W = W(:,IX);
end

% how many pixels for borders?
if nargin < 4
    borders = 1;
end
%fprintf('Visualizing patches\n');
[ndim,nunits]=size(W);
npix = floor(sqrt(ndim)+0.999);
npix2 = floor(sqrt(nunits)+0.999);
minW=min(W(:));
maxW=max(W(:));
bigpic = -(minW+maxW)/2*ones(((npix+borders)*npix2+borders));
if (nunits/npix2<=npix2-1),
    bigpic = bigpic(:,1:(npix+borders)*(npix2-1)+borders);
end;
for i=1:nunits;
    if (horiz)
    bigpic(mod(i-1,npix2)*(npix+borders)+borders+1:mod(i-1,npix2)*(npix+borders)+borders+npix,...
        floor((i-1)/npix2)*(npix+borders)+borders+1:floor((i-1)/npix2)*(npix+borders)+borders+npix)...
        = reshape(W(:,i),npix,npix)';
    else
    bigpic(mod(i-1,npix2)*(npix+borders)+borders+1:mod(i-1,npix2)*(npix+borders)+borders+npix,...
        floor((i-1)/npix2)*(npix+borders)+borders+1:floor((i-1)/npix2)*(npix+borders)+borders+npix)...
        = reshape(W(:,i),npix,npix);
    end
end;
imagesc(bigpic);
colormap(gray);
axis off;
axis equal;
%fprintf('done.\n');


function Q = alex2jaakko(A)
Q.W = A.A;
Q.X = A.S;
Q.mu = A.Mu;

if ~isempty(A.Av)
  D = rows(A.Av{1});
  M = length(A.Av);
  Q.CovW = zeros([D,D,M]);
  for m=1:M
    Q.CovW(:,:,m) = A.Av{m};
  end
end
if ~isempty(A.Sv)
  D = rows(A.Sv{1});
  N = length(A.Sv);
  Q.CovX = zeros([D,D,N]);
  for n=1:N
    Q.CovW(:,:,n) = A.Sv{n};
  end
end

if isempty(A.Muv)
  Q.v_mu = 0;
else
  Q.v_mu = A.Muv;
end


clear
close all
clc;

%time
dt=0.01;

%coeffs
Cg=100.;
Cd=.1;
minSpeed=.5;

name='greenspikes.png.tiff'
sanitizedname=[strrep(name,'.','') '_']
mkdir([sanitizedname 'outputdir'])
%green
%greenheight=double(imread('testgreen.tiff'))/256*1.7;
%greenheight=double(imread('greencone.tiff'))/256*.3;
%greenheight=double(imread('greenconeinv.tiff'))/256*.3;
greenheight=fliplr(rot90(rot90(double(imread(name))/256*.8)));
greenheightPLOT=fliplr(rot90(rot90(double(imread(name))/256*.8)));
[gradX,gradY]=gradient(greenheight(:,:,1));
forceFun=@(R,RL) (RL-R)/dt*Cd + [interp2(-gradX,R(1,:),R(2,:));interp2(-gradY,R(1,:),R(2,:))]*Cg;
%forceFun=@(R,RL) [interp2(-gradX,R(1,:),R(2,:));interp2(-gradY,R(1,:),R(2,:))];
l=size(greenheight,1);

%pin
holeLoc=size(greenheight)'/2;
holeRadius=3;

%graphics
%sph=sphere(30)
alt=30.85;
az=-39+90;
cmapgreen=flipud([181,228,138; 160,220,104; 124,216,87; 81,212,76; 52,188,67; 37,167,60; 32,154,61; 1,114,56; 0,86,19]/255);
stickX=[holeLoc(1),holeLoc(1)];
stickY=[holeLoc(2),holeLoc(2)];
stickZ=[greenheight(floor(holeLoc(1)),floor(holeLoc(1))),greenheight(floor(holeLoc(1)),floor(holeLoc(1)))+100];
flagX=[stickX;stickX+40];
flagY=[stickY;stickY];
flagZ=[stickZ(2),stickZ(2)-30;stickZ(2),stickZ(2)-30];
flagC=zeros(2,2,3);
flagC(:,:,1)=.9;

% balls
startLoc=[64;64];

%angles=(45)*pi/180;
%speeds=400;
%angles=linspace((45-15)*pi/180,(45+15)*pi/180,10);%-pi/4;
angles=linspace((45-90)*pi/180,(45+90)*pi/180,100);%-pi/4;
speeds=linspace(minSpeed,150,100);

numParticles=length(speeds)*length(angles);

speeds=reshape(speeds,1,1,length(speeds));
angleVectors=[cos(angles);sin(angles)];
startConditions=bsxfun(@times,speeds,angleVectors);
startConditions=reshape(startConditions,2,length(speeds)*length(angles));

r=repmat(startLoc,1,numParticles);
rl=r-startConditions*dt;

rstart=r;
rlstart=rl;

%sequentialhits staging
%each ball laucnhes after 1/4 second (300 iters/4) = 80 ticks
launchTicks=80

i=0;
while sum(sum(r~=rl))
    %energy verlet + drag
    i=i+1;
    rn=2*r-rl+(forceFun(r,rl))*dt^2;
    rl=r;
    r=rn;

    %%%LAUNCH CONDITIONS
    if i<50
        r=rstart;
        rl=rlstart;
    end

    %%%STOP CONDITIONS
    %static friction
    dr=rl-r;
    s=sqrt(dr(1,:).^2+dr(2,:).^2)/dt;
    %walls
    haltBallsEdge=(r>l)|(r<1);
    %in the hole
    distToHole=bsxfun(@minus,holeLoc,rl);%use rl not r to check if the ball is in the hole so it can't escape
    distToHole=sqrt(distToHole(1,:).^2+distToHole(2,:).^2);
    %stop those in stop conditions
    holeBalls=(distToHole<holeRadius);
    rl(:,holeBalls)=repmat(holeLoc,1,sum(holeBalls));
    haltBalls=(haltBallsEdge(1,:)|haltBallsEdge(2,:))|(s<minSpeed)|(distToHole<holeRadius);
    r(:,haltBalls)=rl(:,haltBalls);

    if mod(i,10)==0
        figure(1)
        surf(greenheightPLOT,'edgecolor','none')
        colormap(cmapgreen)
        set(gca,'DataAspectRatio',[1 1 1])
        hold on
        scatter3(r(1,:),r(2,:),3+greenheightPLOT(sub2ind(size(greenheightPLOT), floor(r(2,:)),floor(r(1,:)))),'wo','filled')
        plot3(stickX,stickY,stickZ,'k-')
        surf(flagX,flagY,flagZ,flagC,'edgecolor','none')
        hold off
        az=az+.1;
        view([az alt])
%         imshow(greenheight,[min(min(greenheight)),max(max(greenheight))],'colormap',colormap('parula'))
        hold on
        %rectangle('Position',[holeLoc(1)-holeRadius holeLoc(2)-holeRadius holeRadius*2 holeRadius*2],'Curvature',[1,1],'FaceColor','black');
        %scatter(r(1,:),r(2,:),'w.')
        hold off
        xlim([0,512])
        ylim([0,512])
        %title(num2str(s(1)))
        set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0.04, 1, 0.96]);
        saveas(gcf,[[sanitizedname 'outputdir'] '\' num2str(i/10,'%05i') '.png'])
    end
end

%phase space

figure(2)
maxDist=256;
maxColor=reshape([1,0,0],1,1,3);
minColor=reshape([1,1,1],1,1,3);
dists=fliplr(flipud(reshape(distToHole,length(angles),length(speeds))'));
imshow(dists,[holeRadius,maxDist],'colormap',colormap('jet'))
hold on
h=imshow(repmat(ones(size(dists)),1,1,3));
hold off
set(h,'AlphaData',dists<holeRadius);
ylabel('Putt speed')
xlabel('putt angle')


% This file serves as a template of defining the topology of the
% beamforming network with cross entropy training.
% You should create a copy for each of your experiments and name them
% differently.
%
% References:
% [1] Xiong Xiao, Shinji Watanabe, Hakan Erdogan, Liang Lu, John Hershey,
% Michael L. Seltzer, Guoguo Chen, Yu Zhang, Michael Mandel, Dong Yu, "Deep
% beamforming networks for multi-channel speech recognition", in ICASSP
% 2016.
% [2] Xiong Xiao, Shinji Watanabe, Eng Siong Chng, Haizhou Li, "Beamforming
% Networks Using Spatial Covariance Features for Far-field Speech
% Recognition", in APSIPA 2016.
%
% Created by Xiong Xiao, Temasek Laboratories, NTU, Singapore.
% Last Modified: 29 Nov 2016
%
function para = ConfigMaskBFnetCE(para)
para.topology.fs = 16000;   % sampling rate
if isfield(para.topology, 'useChannel')
    if length(para.topology.useChannel)==1      % if useChannel is an integer, use it as the number of channels
        para.topology.nCh = para.topology.useChannel;
    else                                        % is useChannel is an integer array, use the specified channel indexes
        para.topology.nCh = length(para.topology.useChannel);
    end
else
    para.topology.nCh = 2;      % by default use 2 channels
end
para.topology = SetDefaultValue(para.topology, 'useFileName', 0);   % by default load waveforms into memory. If data is too big, we can also use wave file names
para.topology = SetDefaultValue(para.topology, 'nChMask', 1);   % by default use only 1 channel for mask prediction

% define the input type:
%   if set to 1, we will use raw waveform as input and need to define the
%   parameters for extracting features (such as GCC) and generating complex
%   Fourier transform of the input channels.
%   if set to 0, we will load precomputed features and Fourier
%   coefficients.
para.topology = SetDefaultValue(para.topology, 'useWav', 1);    % by default, we use waveform as input to the network

para.topology.fft_len = 512;
para.topology.freqBin = (0:1/para.topology.fft_len:0.5)*2*pi;
para.topology.nFreqBin = length(para.topology.freqBin);
if para.topology.useWav
    % define the parameters for extracting Fourier coefficients
    para.topology.frame_len = para.topology.fs * 0.025;
    para.topology.frame_shift = para.topology.fs * 0.01;
    para.topology.removeDC = 0;     % do not remove DC for faster speed.
    para.topology.win_type = 'hamming';
end

% define the mask predicting subnet type
para.topology = SetDefaultValue(para.topology, 'MaskNetType', 'LSTM');
switch para.topology.MaskNetType
    case 'DNN'
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSizeMask', [1024]);
        para.topology = SetDefaultValue(para.topology, 'contextSizeMask', 11);  % for DNN, we use 11 frames of consecutive frames
    case 'LSTM'
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSizeMask', [512]);
        para.topology = SetDefaultValue(para.topology, 'useDeltaMask', 1);    % for LSTM, we use delta features without splicing
end

% define the BF subnet type
para.topology = SetDefaultValue(para.topology, 'BfNetType', 'MVDR');      % choose frame DNN or LSTM, default is DNN
switch para.topology.BfNetType
    case 'MVDR'     % use the MVDR formula to obtain beamforming weights

    case 'DNN'      % use DNN to predict beamforming weights
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSizeBF', [1024]);
    case 'LSTM'
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSizeBF', [1024]);
end
para.topology.bf_weight_dim = (para.topology.fft_len/2+1) * para.topology.nCh * 2;  % number of dimensions for weight matrix

% define the AM subnet type
para.topology = SetDefaultValue(para.topology, 'AmNetType', 'DNN');      % choose frame DNN or LSTM, default is DNN
switch para.topology.AmNetType
    case 'DNN'
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSizeAM', [1024]);
    case 'LSTM'
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSizeAM', [1024]);
end
para.topology = SetDefaultValue(para.topology, 'nSenone', 100);
para.topology = SetDefaultValue(para.topology, 'nFbank', 40);

% define the initialized subnets. Just put the path to the fields. Note
% that you can only set either initalAM_CE or initalAM_RBM.

% initial network for mask predicting subnet.
para.topology = SetDefaultValue(para.topology, 'initialMask', '');
% initial network for beamforming predicting subnet. You need to make sure
% that the topology in the initialized network is the same as the topology
% of beamforming subnet defined above.
para.topology = SetDefaultValue(para.topology, 'initialBF', '');
% initial network for acoustic model trained by cross entropy
para.topology = SetDefaultValue(para.topology, 'initialAM_CE', '');
% initial network for acoustic model trained by RBM
para.topology = SetDefaultValue(para.topology, 'initialAM_RBM', '');

% tell the network whether we should update the Mask subnet, the BF subnet, the AM subnet,
% or all of them.
para.topology = SetDefaultValue(para.topology, 'updateMask', 1);
para.topology = SetDefaultValue(para.topology, 'updateBF', 1);
para.topology = SetDefaultValue(para.topology, 'updateAM', 1);

end


function main
close all
problemNames  = {'DenoisingEinstein';'AcceleratedDenoisingEinstein'};

for iproblem = 1:length(problemNames)
    pName = problemNames{iproblem};
    sLoader      = SettingsLoader(pName);
    settings     = sLoader.settings;
    denoisingProblem = DenoisingProblem(settings);
    denoisingProblem.solve();
    pD = denoisingProblem.plottingData;
    figure(1)
    hold on
    plot(pD.cost)
    figure(2)
    hold on
    plot(pD.dualGap)
end

end


function [outStr outNum] = gunits(before,after)
%Function to convert units using Google
%SCd 09/01/2010
%
%gunits searches using the Google convention e.g: '3ft to in'
%
%Input Arguments:
%   -before: string with number and unit such as:
%         '3ft', '17c','17lbf/in^2', '3 ft*lbf'
%   -after: unit you wish to convert such as: (respectively)
%       'mm', 'f', 'N/ft^2','Newton*m'
%
%   NOTE1: Google can be picky with the input.  It's recommended
%       to spell everything out and fill in multiplication/division/powers
%       if you're having issues.  Example:
%
%       >>gunits('3psi','psf')
%           ans = '3 psi' %if outNum was called; an error would've been produced
%
%       >>gunits('3lbf/in^2','lbf/ft^2')
%           ans = 3 (lbf / (in^2)) = 432 lbf / (ft^2)
%
%   NOTE2: The units should be distinguishable with spaces removed e.g:
%      'lbf ft' becomes 'lbfft' which is not a unit.  To fix use 'lbf*ft'
%
%Output Arguments:
%   -outStr: string with the conversion
%   -outNum: numeric value of answer (only if asked for)
%
%NOTE/DISCLAIMER:
%   The algorithm used for retrieving the string is based solely on Google's
%   web format.  As (unfortunately!), I do not own or control Google, their
%   format is subject to change, which could nullify the results of this program.
%   Please let me know if this happens.
%

%Error checking:
assert(nargin==2,'gunits() expects two and only two input arguments!');
assert(ischar(before),'gunits expected its first input argument to be a string!');
assert(ischar(after),'gunits expected its second input argument to be a string!');

%Create search string, remove spaces, read it
search_string = ['http://www.google.com/search?hl=en&source=hp&q=' before '+to+' after];
S = urlread(search_string(~isspace(search_string)));

%The first HTML bold ('') in the returned string will be the initiallization of the
%answer.  Find it and corresponding close bold ('').
strinit = strfind(lower(S),'');
strend = strfind(lower(S),'');
if isempty(strinit) || isempty(strend)
    error('Input units were not accepted: please try again!');
end
strinit = strinit(1);
strend = strend(strend>strinit);
strend = strend(1);

%Output the answer (remove the , < found earlier)
outStr = S(strinit+3:strend-1);

%If the numeric value is wanted:
if nargout == 2
    %Split into parts; find equal sign; keep value after equal sign, remove
    %spaces that Google uses to show 1000's
    parts = regexp(outStr,' ','split');
    eqsign = cellfun(@(x)strcmp(x,'='),parts);
    assert(any(eqsign),'The conversion did not work: please try again');
    outNum = parts{find(eqsign)+1};
    outNum = str2double(outNum(~isspace(outNum)));
end


function data = plotData(f, g, h)
%PLOTDATA   Useful data values for plotting a CHEBTECH object.
%   DATA = PLOTDATA(F) returns a struct containing data that can be used for
%   plotting F. The struct DATA contains the following fields:
%
%       xLine: x-coordinates of for plotting smooth curves.
%       yLine: Function values of F at the coordinates stored in xLine.
%       xPoints: x-coordinates of the Chebyshev points used to represent F.
%       yPoints: Function value at the Chebyshev points used to represent F.
%
%   DATA.xLine and DATA.yLine are used for plotting smooth curves (usually
%   passed to PLOT() with the '-' option).
%
%   DATA.xPoints and DATA.yPoints contain the (x, F(x)) data at the Chebyshev
%   grid used to represent F, and are used for plots with marks (e.g.
%   PLOT(F,'-o').
%
%   DATA = PLOTDATA(F, G) is similar but for plot calls of the form PLOT(F, G),
%   where both F and G are CHEBTECH objects.
%
%   DATA = PLOTDATA(F, G, H) is for plots of the form PLOT3(F, G, H). In this
%   instance, DATA also contains fields zLine and zPoints for the data
%   corresponding to H.
%
% See also PLOT.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

if ( nargin == 1 )
    g = [];
end
if ( nargin < 3 )
    h = [];
end

% Get the number of points: (Oversample the wavelength)
len = max([length(f), length(g), length(h)]);
npts = min(max(501, round(4*pi*len)), chebtech.techPref().maxLength);

% Initialise the output structure:
data = struct('xLine', [], 'yLine', [], 'xPoints', [], 'yPoints', [], ...
    'xLim', [], 'yLim', [], 'defaultXLim', 1, 'defaultYLim', 1);

if ( isempty(g) )
    % PLOT(F):

    % Values on oversampled Chebyshev grid (faster than evaluating a uniform grid!).
    data.xLine = f.chebpts(npts);
    data.yLine = get(prolong(f, npts), 'values');

    % Values on the Cheyshev grid tied to the CHEBTECH F:
    data.xPoints = f.points();
    data.yPoints = f.coeffs2vals(f.coeffs);

    % yLim:
    data.yLim = [min(data.yLine(:)) max(data.yLine(:))];

    % xLim:
    data.xLim = [-1 1];

elseif ( isa(g, 'chebtech') )
    % PLOT(F, G)

    % Also return the grid points used.
    % Grid data for f:
    data.fGrid.xLine = f.chebpts(npts);
    % Use the maximum of the lenghts of f, g and h to match the number of
    % values returned:
    data.fGrid.xPoints = f.chebpts(len);

    % Grid data for g:
    data.gGrid.xLine = g.chebpts(npts);
    % Use the maximum of the lenghts of f, g and h to match the number of
    % values returned:
    data.gGrid.xPoints = g.chebpts(len);

    % Values on oversampled Chebyshev grid (faster than evaluating a uniform grid!).
    data.xLine = get(prolong(f, npts), 'values');
    data.yLine = get(prolong(g, npts), 'values');

    % Values on the largest Cheyshev grid tied to the CHEBTECH objects F and G:
    data.xPoints = get(prolong(f, len), 'values');
    data.yPoints = get(prolong(g, len), 'values');

    % xLim:
    xdata = [get(f, 'lval'); data.xLine; get(f, 'rval')];
    data.xLim = [min(xdata(:)) max(xdata(:))];

    % yLim:
    ydata = [get(g, 'lval'); data.yLine; get(g, 'rval')];
    data.yLim = [min(ydata(:)) max(ydata(:))];

    if ( isa(h, 'chebtech') )
        % PLOT3(F, G, H)

        % Grid data for h:
        data.hGrid.xLine = h.chebpts(npts);
        % Use the maximum of the lenghts of f, g and h to match the number of
        % values returned:
        data.hGrid.xPoints = h.chebpts(len);

         % Values on oversampled Chebyshev grid:
        data.zLine = get(prolong(h, npts), 'values');
        data.zPoints = get(prolong(h, len), 'values');

    end

else

    error('CHEBFUN:CHEBTECH:plotData:dataType', 'Invalid data types.');

end

end