function [source] = ft_sourceanalysis(cfg, data, baseline)

% FT_SOURCEANALYSIS performs beamformer dipole analysis on EEG or MEG data
% after preprocessing and a timelocked or frequency analysis
%
% Use as
%   [source] = ft_sourceanalysis(cfg, freq)
% or
%   [source] = ft_sourceanalysis(cfg, timelock)
%
% where the second input argument with the data should be organised in a structure
% as obtained from the FT_FREQANALYSIS or FT_TIMELOCKANALYSIS function. The
% configuration "cfg" is a structure containing information about source positions
% and other options.
%
% The different source reconstruction algorithms that are implemented are
%   cfg.method     = 'lcmv'    linear constrained minimum variance beamformer
%                    'sam'     synthetic aperture magnetometry
%                    'dics'    dynamic imaging of coherent sources
%                    'pcc'     partial cannonical correlation/coherence
%                    'mne'     minimum norm estimation
%                    'rv'      scan residual variance with single dipole
%                    'music'   multiple signal classification
%                    'sloreta' standardized low-resolution electromagnetic tomography
%                    'eloreta' exact low-resolution electromagnetic tomography
% The DICS and PCC methods are for frequency or time-frequency domain data, all other
% methods are for time domain data. ELORETA can be used both for time, frequency and
% time-frequency domain data.
%
% The complete grid with dipole positions and optionally precomputed leadfields is
% constructed using FT_PREPARE_SOURCEMODEL. It can be specified as as a regular 3-D
% grid that is aligned with the axes of the head coordinate system using
%   cfg.xgrid               = vector (e.g. -20:1:20) or 'auto' (default = 'auto')
%   cfg.ygrid               = vector (e.g. -20:1:20) or 'auto' (default = 'auto')
%   cfg.zgrid               = vector (e.g.   0:1:20) or 'auto' (default = 'auto')
%   cfg.resolution          = number (e.g. 1 cm) for automatic grid generation
% If the source model destribes a triangulated cortical sheet, it is described as
%   cfg.sourcemodel.pos     = N*3 matrix with the vertex positions of the cortical sheet
%   cfg.sourcemodel.tri     = M*3 matrix that describes the triangles connecting the vertices
% Alternatively the position of a few dipoles at locations of interest can be
% user-specified, for example obtained from an anatomical or functional MRI
%   cfg.sourcemodel.pos     = N*3 matrix with position of each source
%   cfg.sourcemodel.inside  = N*1 vector with boolean value whether grid point is inside brain (optional)
%   cfg.sourcemodel.dim     = [Nx Ny Nz] vector with dimensions in case of 3-D grid (optional)
%
% Besides the source positions, you may also include previously computed
% spatial filters and/or leadfields using
%   cfg.sourcemodel.filter
%   cfg.sourcemodel.leadfield
%
% The following strategies are supported to obtain statistics for the source parameters using
% multiple trials in the data, either directly or through a resampling-based approach
%   cfg.rawtrial      = 'no' or 'yes'   construct filter from single trials, apply to single trials. Note that you also may want to set cfg.keeptrials='yes' to keep all trial information, especially if using in combination with sourcemodel.filter
%   cfg.jackknife     = 'no' or 'yes'   jackknife resampling of trials
%   cfg.pseudovalue   = 'no' or 'yes'   pseudovalue resampling of trials
%   cfg.bootstrap     = 'no' or 'yes'   bootstrap resampling of trials
%   cfg.numbootstrap  = number of bootstrap replications (e.g. number of original trials)
% If none of these options is specified, the average over the trials will
% be computed prior to computing the source reconstruction.
%
% To obtain statistics over the source parameters between two conditions, you
% can also use a resampling procedure that reshuffles the trials over both
% conditions. In that case, you should call the function with two datasets
% containing single trial data like
%   [source] = ft_sourceanalysis(cfg, freqA, freqB)
%   [source] = ft_sourceanalysis(cfg, timelockA, timelockB)
% and you should specify
%   cfg.randomization      = 'no' or 'yes'
%   cfg.permutation        = 'no' or 'yes'
%   cfg.numrandomization   = number, e.g. 500
%   cfg.numpermutation     = number, e.g. 500 or 'all'
%
% If you have not specified a sourcemodel with pre-computed leadfields,
% the leadfield for each source position will be computed on the fly.
% In that case you can modify the leadfields by reducing the rank
% (i.e.  remove the weakest orientation), or by normalizing each
% column.
%   cfg.reducerank  = 'no', or number (default = 3 for EEG, 2 for MEG)
%   cfg.normalize   = 'no' or 'yes' (default = 'no')
%
% Other configuration options are
%   cfg.channel       = Nx1 cell-array with selection of channels (default = 'all'),
%                       see FT_CHANNELSELECTION for details
%   cfg.frequency     = single number (in Hz)
%   cfg.latency       = single number in seconds, for time-frequency analysis
%   cfg.lambda        = number or empty for automatic default
%   cfg.kappa         = number or empty for automatic default
%   cfg.tol           = number or empty for automatic default
%   cfg.refchan       = reference channel label (for coherence)
%   cfg.refdip        = reference dipole location (for coherence)
%   cfg.supchan       = suppressed channel label(s)
%   cfg.supdip        = suppressed dipole location(s)
%   cfg.keeptrials    = 'no' or 'yes'
%   cfg.keepleadfield = 'no' or 'yes'
%   cfg.projectnoise  = 'no' or 'yes'
%   cfg.keepfilter    = 'no' or 'yes'
%   cfg.keepcsd       = 'no' or 'yes'
%   cfg.keepmom       = 'no' or 'yes'
%   cfg.feedback      = 'no', 'text', 'textbar', 'gui' (default = 'text')
%
% The volume conduction model of the head should be specified as
%   cfg.headmodel     = structure with volume conduction model, see FT_PREPARE_HEADMODEL
%
% The EEG or MEG sensor positions can be present in the data or can be specified as
%   cfg.elec          = structure with electrode positions or filename, see FT_READ_SENS
%   cfg.grad          = structure with gradiometer definition or filename, see FT_READ_SENS
%
% To facilitate data-handling and distributed computing you can use
%   cfg.inputfile   =  ...
%   cfg.outputfile  =  ...
% If you specify one of these (or both) the input data will be read from a *.mat
% file on disk and/or the output data will be written to a *.mat file. These mat
% files should contain only a single variable, corresponding with the
% input/output structure.
%
% See also FT_SOURCEDESCRIPTIVES, FT_SOURCESTATISTICS, FT_PREPARE_LEADFIELD,
% FT_PREPARE_HEADMODEL, FT_PREPARE_SOURCEMODEL

% Undocumented local options:
% cfg.numcomponents
% cfg.refchannel
% cfg.trialweight   = 'equal' or 'proportional'
% cfg.powmethod     = 'lambda1' or 'trace'

% Copyright (c) 2003-2008, F.C. Donders Centre, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble debug
ft_preamble loadvar data baseline
ft_preamble provenance data baseline
ft_preamble trackconfig

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

% the baseline data can be passed as input argument or can be read from disk
hasbaseline = exist('baseline', 'var');

% check if the input data is valid for this function
data = ft_checkdata(data, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes');

if hasbaseline
  baseline = ft_checkdata(baseline, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes');
end

% check that the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'renamed',    {'toilim', 'latency'});
cfg = ft_checkconfig(cfg, 'renamed',    {'foilim', 'frequency'});
cfg = ft_checkconfig(cfg, 'renamed',    {'jacknife', 'jackknife'});
cfg = ft_checkconfig(cfg, 'renamed',    {'refchannel', 'refchan'});
cfg = ft_checkconfig(cfg, 'renamedval', {'method', 'power',           'dics'});
cfg = ft_checkconfig(cfg, 'renamedval', {'method', 'coh_refchan',     'dics'});
cfg = ft_checkconfig(cfg, 'renamedval', {'method', 'coh_refdip',      'dics'});
cfg = ft_checkconfig(cfg, 'renamedval', {'method', 'dics_cohrefchan', 'dics'});
cfg = ft_checkconfig(cfg, 'renamedval', {'method', 'dics_cohrefdip',  'dics'});
cfg = ft_checkconfig(cfg, 'forbidden',  {'parallel', 'trials'});
cfg = ft_checkconfig(cfg, 'forbidden',  {'foi', 'toi'});
cfg = ft_checkconfig(cfg, 'renamed',    {'hdmfile', 'headmodel'});
cfg = ft_checkconfig(cfg, 'renamed',    {'vol',     'headmodel'});
cfg = ft_checkconfig(cfg, 'renamed',    {'grid',    'sourcemodel'});
cfg = ft_checkconfig(cfg, 'renamed',    {'elecfile', 'elec'});
cfg = ft_checkconfig(cfg, 'renamed',    {'gradfile', 'grad'});
cfg = ft_checkconfig(cfg, 'renamed',    {'optofile', 'opto'});

% determine the type of input data
isfreq     = ft_datatype(data, 'freq');
iscomp     = ft_datatype(data, 'comp');
istimelock = ft_datatype(data, 'timelock');
if all(~[isfreq iscomp istimelock])
  ft_error('input data is not recognized');
end

% set the defaults
cfg.keeptrials       = ft_getopt(cfg, 'keeptrials', 'no');
cfg.keepleadfield    = ft_getopt(cfg, 'keepleadfield', 'no');
cfg.trialweight      = ft_getopt(cfg, 'trialweight', 'equal');
cfg.jackknife        = ft_getopt(cfg, 'jackknife',   'no');
cfg.pseudovalue      = ft_getopt(cfg, 'pseudovalue', 'no');
cfg.bootstrap        = ft_getopt(cfg, 'bootstrap',   'no');
cfg.singletrial      = ft_getopt(cfg, 'singletrial', 'no');
cfg.rawtrial         = ft_getopt(cfg, 'rawtrial',    'no');
cfg.randomization    = ft_getopt(cfg, 'randomization', 'no');
cfg.numrandomization = ft_getopt(cfg, 'numrandomization', 100);
cfg.permutation      = ft_getopt(cfg, 'permutation',      'no');
cfg.numpermutation   = ft_getopt(cfg, 'numpermutation',   100);
cfg.wakewulf         = ft_getopt(cfg, 'wakewulf', 'yes');
cfg.killwulf         = ft_getopt(cfg, 'killwulf', 'yes');
cfg.channel          = ft_getopt(cfg, 'channel',  'all');
cfg.supdip           = ft_getopt(cfg, 'supdip',        []);
cfg.latency          = ft_getopt(cfg, 'latency',   'all');
cfg.frequency        = ft_getopt(cfg, 'frequency', 'all');

if istimelock
  cfg.method = ft_getopt(cfg, 'method', 'lcmv');
elseif isfreq
  cfg.method = ft_getopt(cfg, 'method', 'dics');
else
  cfg.method = ft_getopt(cfg, 'method', []);
end

% put the low-level options pertaining to the source reconstruction method in their own field
cfg = ft_checkconfig(cfg, 'createsubcfg',  cfg.method);

% put the low-level options pertaining to the dipole grid in their own field
cfg = ft_checkconfig(cfg, 'renamed', {'tightgrid', 'tight'});  % this is moved to cfg.sourcemodel.tight by the subsequent createsubcfg
cfg = ft_checkconfig(cfg, 'renamed', {'sourceunits', 'unit'}); % this is moved to cfg.sourcemodel.unit  by the subsequent createsubcfg

% put the low-level options pertaining to the sourcemodel in their own field
cfg = ft_checkconfig(cfg, 'createsubcfg', {'sourcemodel'});
% move some fields from cfg.sourcemodel back to the top-level configuration
cfg = ft_checkconfig(cfg, 'createtopcfg', {'sourcemodel'});

cfg.(cfg.method).keepfilter    = ft_getopt(cfg.(cfg.method), 'keepfilter',    'no');
cfg.(cfg.method).keepcsd       = ft_getopt(cfg.(cfg.method), 'keepcsd',       'no');
cfg.(cfg.method).keepmom       = ft_getopt(cfg.(cfg.method), 'keepmom',       'yes');
cfg.(cfg.method).projectnoise  = ft_getopt(cfg.(cfg.method), 'projectnoise',  'no');
cfg.(cfg.method).feedback      = ft_getopt(cfg.(cfg.method), 'feedback',      'text');
cfg.(cfg.method).lambda        = ft_getopt(cfg.(cfg.method), 'lambda',        []);
cfg.(cfg.method).kappa         = ft_getopt(cfg.(cfg.method), 'kappa',         []);
cfg.(cfg.method).tol           = ft_getopt(cfg.(cfg.method), 'tol',           []);
cfg.(cfg.method).invmethod     = ft_getopt(cfg.(cfg.method), 'invmethod',     []);
cfg.(cfg.method).powmethod     = ft_getopt(cfg.(cfg.method), 'powmethod',     []);
cfg.(cfg.method).normalize     = ft_getopt(cfg.(cfg.method), 'normalize',     'no');
cfg.(cfg.method).reducerank    = ft_getopt(cfg.(cfg.method), 'reducerank',    []); % the default for this is handled below

if hasbaseline && (strcmp(cfg.randomization, 'no') && strcmp(cfg.permutation, 'no'))
  ft_error('input of two conditions only makes sense if you want to randomize or permute');
elseif ~hasbaseline && (strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes'))
  ft_error('randomization or permutation requires that you give two conditions as input');
end

if isfield(cfg, 'latency') && ischar(cfg.latency) && strcmp(cfg.latency, 'all') && istimelock
  %error('specification of cfg.latency is only required for time-frequency data');
end

if sum([strcmp(cfg.jackknife, 'yes'), strcmp(cfg.bootstrap, 'yes'), strcmp(cfg.pseudovalue, 'yes'), strcmp(cfg.singletrial, 'yes'), strcmp(cfg.rawtrial, 'yes'), strcmp(cfg.randomization, 'yes'), strcmp(cfg.permutation, 'yes')])>1
  ft_error('jackknife, bootstrap, pseudovalue, singletrial, rawtrial, randomization and permutation are mutually exclusive');
end

if strcmp(cfg.rawtrial, 'yes') && isfield(cfg, 'sourcemodel') && ~isfield(cfg.sourcemodel, 'filter')
  ft_warning('Using each trial to compute its own filter is not currently recommended. Use this option only with precomputed filters in cfg.sourcemodel.filter');
end

% start with an empty output structure
source = [];

if istimelock
  % add the time axis to the output
  tmpcfg = keepfields(cfg, {'channel', 'latency', 'showcallinfo'});
  tmpcfg.avgovertime = 'no';
  data = ft_selectdata(tmpcfg, data);
  % restore the provenance information
  [cfg, data] = rollback_provenance(cfg, data);

  % copy the descriptive fields to the output
  source = copyfields(data, source, {'time'});

elseif isfreq
  tmpcfg = keepfields(cfg, {'channel', 'latency', 'frequency', 'refchan', 'nanmean', 'showcallinfo'});

  % ensure that the refchan is kept, if present
  if isfield(tmpcfg, 'refchan') && ~isempty(tmpcfg.refchan) && isempty(match_str(tmpcfg.channel, tmpcfg.refchan))
    hasrefchan = 1;
  else
    hasrefchan = 0;
  end

  if hasrefchan
    if ischar(tmpcfg.refchan), tmpcfg.refchan = {tmpcfg.refchan}; end
    tmpchannel     = ft_channelselection(tmpcfg.channel, data.label); % the channels needed for the spatial filter
    tmpcfg.channel = cat(1, tmpchannel, tmpcfg.refchan);
    tmpcfg         = rmfield(tmpcfg, 'refchan');
  end

  tmpcfg.avgoverfreq = 'yes';
  if isfield(data, 'time')
    tmpcfg.avgovertime = 'yes';
  end
  data = ft_selectdata(tmpcfg, data);
  % restore the provenance information
  [cfg, data] = rollback_provenance(cfg, data);

  if hasrefchan, cfg.channel = match_str(data.label, tmpchannel); end

  % copy the descriptive fields to the output
  source = copyfields(data, source, {'time', 'freq', 'cumtapcnt'});

  % HACK the remainder of the code expects a single number
  cfg.frequency = mean(cfg.frequency);
  if isfield(data, 'time')
    cfg.latency   = mean(cfg.latency);
  end

elseif iscomp
  % FIXME, select the components here
  % FIXME, add the component numbers to the output
  ft_error('the use of component data in ft_sourceanalysis is disabled for the time being: if you encounter this error message and you need this functionality please contact the FieldTrip development team');
end

convertcomp = false;
if iscomp && (strcmp(cfg.method, 'rv') || strcmp(cfg.method, 'music'))
  % these timelock methods are also supported for frequency or component data
  if iscomp
    convertcomp = true;
    % the conversion will be done below, after the latency and channel selection
  end
elseif isfreq && isfield(data, 'labelcmb')
  % ensure that the cross-spectral densities are chan_chan_therest,
  % otherwise the latency and frequency selection could fail, so we don't
  % need to worry about linearly indexed cross-spectral densities below
  % this point, this step may take some time, if multiple trials are
  % present in the data
  fprintf('converting the linearly indexed channelcombinations into a square CSD-matrix\n');
  data = ft_checkdata(data, 'cmbrepresentation', 'full');
end

if isfreq
  % as per the call to ft_checkdata above, the dimord of the freq-data is
  % either (rpt_)chan_chan_otherstuff, or rpttap_chan_otherstuff. The
  % former is with cross-spectra, the latter is with fourierspctrm

  % previously there was some explicit dimord checking here, but I think
  % with the more consistent data handling it is not necessary anymore.
end

% collect and preprocess the electrodes/gradiometer and head model
[headmodel, sens, cfg] = prepare_headmodel(cfg, data);

% set the default for reducing the rank of the leadfields
if isempty(cfg.(cfg.method).reducerank)
  if ft_senstype(sens, 'eeg')
    cfg.(cfg.method).reducerank = 'no';    % for EEG
  elseif ft_senstype(sens, 'meg') && ft_headmodeltype(headmodel, 'infinite')
    cfg.(cfg.method).reducerank = 'no';    % for MEG with a magnetic dipole, e.g. a HPI coil
  elseif ft_senstype(sens, 'meg')
    cfg.(cfg.method).reducerank = 'yes';   % for MEG with a current dipole in a volume conductor
  end
end

% It might be that the number of channels in the data, the number of
% channels in the electrode/gradiometer definition and the number of
% channels in the localspheres volume conduction model are different.
% Hence a subset of the data channels will be used.
Nchans = length(cfg.channel);

if strcmp(cfg.keepleadfield, 'yes') && (~isfield(cfg, 'sourcemodel') || ~isfield(cfg.sourcemodel, 'leadfield'))
  % precompute the leadfields upon the users request
  fprintf('precomputing leadfields\n');
  sourcemodel = ft_prepare_leadfield(cfg, data);
elseif (strcmp(cfg.permutation,   'yes') || ...
    strcmp(cfg.randomization, 'yes') || ...
    strcmp(cfg.bootstrap,     'yes') || ...
    strcmp(cfg.jackknife,     'yes') || ...
    strcmp(cfg.pseudovalue,   'yes') || ...
    strcmp(cfg.singletrial,   'yes') || ...
    strcmp(cfg.rawtrial,      'yes')) && (~isfield(cfg, 'sourcemodel') || ~isfield(cfg.sourcemodel, 'leadfield'))
  % also precompute the leadfields if multiple trials have to be processed
  fprintf('precomputing leadfields for efficient handling of multiple trials\n');
  sourcemodel = ft_prepare_leadfield(cfg, data);
else
  % only prepare the source positions, the leadfield will be computed on the fly if not present

  % copy all options that are potentially used in ft_prepare_sourcemodel
  tmpcfg           = keepfields(cfg, {'sourcemodel', 'mri', 'headshape', 'symmetry', 'smooth', 'threshold', 'spheremesh', 'inwardshift', 'xgrid' 'ygrid', 'zgrid', 'resolution', 'tight', 'warpmni', 'template', 'showcallinfo'});
  tmpcfg.headmodel = headmodel;
  if ft_senstype(sens, 'eeg')
    tmpcfg.elec = sens;
  elseif ft_senstype(sens, 'meg')
    tmpcfg.grad = sens;
  end
  % construct the dipole positions on which the source reconstruction will be done
  sourcemodel = ft_prepare_sourcemodel(tmpcfg);
  if ischar(cfg.sourcemodel)
    cfg.sourcemodel = sourcemodel;
  end
end

if isfield(cfg.sourcemodel, 'filter')
  if numel(cfg.sourcemodel.filter) == size(sourcemodel.pos, 1)
    sourcemodel.filter = cfg.sourcemodel.filter;
  else
    ft_warning('ignoring predefined filter as it does not match the number of source positions');
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% do frequency domain source reconstruction
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if isfreq && any(strcmp(cfg.method, {'dics', 'pcc', 'eloreta', 'mne','harmony', 'rv', 'music'}))

  switch cfg.method
    case 'pcc'
      % this can handle both a csd matrix and a fourier matrix, but needs
      % special handling of the refdip etc.
      cfg.refdip = ft_getopt(cfg, 'refdip', []);
      cfg.supdip = ft_getopt(cfg, 'supdip', []);
      cfg.refchan = ft_getopt(cfg, 'refchan', []);
      cfg.supchan = ft_getopt(cfg, 'supchan', []);
      cfg.refchan = ft_channelselection(cfg.refchan, data.label);
      cfg.supchan = ft_channelselection(cfg.supchan, data.label);

      % HACK: use some experimental code
      if hasbaseline
        ft_error('not supported')
      end

      tmpcfg         = cfg;
      tmpcfg.refchan = ''; % prepare_freq_matrices should not know explicitly about the refchan
      tmpcfg.channel = cfg.channel(:)';
      if isfield(cfg, 'refchan')
        % add the refchan implicitely
        tmpcfg.channel = [tmpcfg.channel cfg.refchan(:)'];
      end
      if isfield(cfg, 'supchan')
        % add the supchan implicitely
        tmpcfg.channel = [tmpcfg.channel cfg.supchan(:)'];
      end

      % select the data in the channels and the frequency of interest
      [Cf, Cr, Pr, Ntrials, tmpcfg] = prepare_freq_matrices(tmpcfg, data);

      if isfield(cfg, 'refchan') && ~isempty(cfg.refchan)
        [dum, refchanindx] = match_str(cfg.refchan, tmpcfg.channel);
      else
        refchanindx = [];
      end
      if isfield(cfg, 'supchan') && ~isempty(cfg.supchan)
        [dum, supchanindx] = match_str(cfg.supchan,tmpcfg.channel);
      else
        supchanindx = [];
      end
      Nchans = length(tmpcfg.channel); % update the number of channels

      % if the input data has a complete fourier spectrum, it can be projected through the filters
      if isfield(data, 'fourierspctrm')
        [dum, datchanindx] = match_str(tmpcfg.channel, data.label);
        fbin = nearest(data.freq, cfg.frequency);
        if strcmp(data.dimord, 'chan_freq')
          avg = data.fourierspctrm(datchanindx, fbin);
        elseif strcmp(data.dimord, 'rpt_chan_freq') || strcmp(data.dimord, 'rpttap_chan_freq')
          avg = transpose(data.fourierspctrm(:, datchanindx, fbin));
        elseif strcmp(data.dimord, 'chan_freq_time')
          tbin = nearest(data.time, cfg.latency);
          avg = data.fourierspctrm(datchanindx, fbin, tbin);
        elseif strcmp(data.dimord, 'rpt_chan_freq_time') || strcmp(data.dimord, 'rpttap_chan_freq_time')
          tbin = nearest(data.time, cfg.latency);
          avg  = transpose(data.fourierspctrm(:, datchanindx, fbin, tbin));
        end
      else
        avg = [];
      end

    case {'eloreta' 'mne' 'rv' 'music' 'harmony'}
      % these can handle both a csd matrix and a fourier matrix
      [Cf, Cr, Pr, Ntrials, cfg] = prepare_freq_matrices(cfg, data);

      % if the input data has a complete fourier spectrum, it can be projected through the filters
      if isfield(data, 'fourierspctrm')
        [dum, datchanindx] = match_str(cfg.channel, data.label);
        fbin = nearest(data.freq, cfg.frequency);
        if strcmp(data.dimord, 'chan_freq')
          avg = data.fourierspctrm(datchanindx, fbin);
        elseif strcmp(data.dimord, 'rpt_chan_freq') || strcmp(data.dimord, 'rpttap_chan_freq')
          avg = transpose(data.fourierspctrm(:, datchanindx, fbin));
        elseif strcmp(data.dimord, 'chan_freq_time')
          tbin = nearest(data.time, cfg.latency);
          avg = data.fourierspctrm(datchanindx, fbin, tbin);
        elseif strcmp(data.dimord, 'rpt_chan_freq_time') || strcmp(data.dimord, 'rpttap_chan_freq_time')
          tbin = nearest(data.time, cfg.latency);
          avg  = transpose(data.fourierspctrm(:, datchanindx, fbin, tbin));
        end
      else % The input data is a CSD matrix, this is enough for computing source power, coherence and residual power.
        avg = Cf;
      end

    case 'dics'

      [Cf, Cr, Pr, Ntrials, cfg] = prepare_freq_matrices(cfg, data);

      % assign a descriptive name to each of the dics sub-methods, the default is power only
      if isfield(cfg, 'refdip') && ~isempty(cfg.refdip);
        submethod = 'dics_refdip';
      elseif isfield(cfg, 'refchan') && ~isempty(cfg.refchan);
        submethod = 'dics_refchan';
      else
        submethod = 'dics_power';
      end

    otherwise
  end

  % This is the place to check for the consistency of the channel order in
  % the pre-computed leadfields/spatial filters, and to correct for it, if
  % necessary. This pertains to bugs 1746 and 3029.
  if isfield(sourcemodel, 'label') && (isfield(sourcemodel, 'leadfield') || isfield(sourcemodel, 'filter'))
    % match the channels in the leadfields/filters with those in the data
    [i1, i2] = match_str(cfg.channel, sourcemodel.label);
    if ~isequal(i2(:), (1:numel(sourcemodel.label))')
      if isfield(sourcemodel, 'leadfield')
        fprintf('\n\nSubselecting/reordering the channels in the precomputed leadfields\n\n');
        inside_indx = find(sourcemodel.inside);
        for k = inside_indx(:)'
          sourcemodel.leadfield{k} = sourcemodel.leadfield{k}(i2, :);
        end
      end
      if isfield(sourcemodel, 'filter')
        fprintf('\n\nSubselecting/reordering the channels in the precomputed filters\n\n');
        inside_indx = find(sourcemodel.inside);
        for k = inside_indx(:)'
          sourcemodel.filter{k} = sourcemodel.filter{k}(:, i2);
        end
      end
      sourcemodel.label = sourcemodel.label(i2);
    end
    if ~isequal(i1(:), (1:numel(cfg.channel))')
      % this is not so easy to deal with, throw an error
      ft_error('There''s a mismatch between the number/order of channels in the data, with respect to the channels in the precomputed leadfield/filter. This is not easy to solve automatically. Please look into this.');
    end
  end

  % fill these with NaNs, so that I dont have to treat them separately
  if isempty(Cr), Cr = nan(Ntrials, Nchans, 1); end
  if isempty(Pr), Pr = nan(Ntrials, 1, 1); end

  if hasbaseline
    % repeat the conversion for the baseline condition
    [bCf, bCr, bPr, Nbaseline, cfg] = prepare_freq_matrices(cfg, baseline);
    % fill these with NaNs, so that I dont have to treat them separately
    if isempty(bCr), bCr = nan(Nbaseline, Nchans, 1); end
    if isempty(bPr), bPr = nan(Nbaseline, 1, 1); end
    % rename the active condition for convenience
    aCf = Cf;
    aCr = Cr;
    aPr = Pr;
    % this is required for averaging 2 conditions using prepare_resampled_data
    cfg2 = [];
    cfg2.numcondition = 2;
    % this is required for randomizing/permuting 2 conditions using prepare_resampled_data
    cfg.numcondition = 2;
  end

  % prepare the resampling of the trials, or average the data if multiple trials are present and no resampling is necessary
  if (Ntrials<=1) && (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes') || strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes'))
    ft_error('multiple trials required in the data\n');

  elseif strcmp(cfg.permutation, 'yes')
    % compute the cross-spectral density matrix without resampling
    [dum, avg_aCf, avg_aCr, avg_aPr, avg_bCf, avg_bCr, avg_bPr] = prepare_resampled_data(cfg2 , aCf, aCr, aPr, bCf, bCr, bPr);
    % compute the cross-spectral density matrix with random permutation
    [dum, rnd_aCf, rnd_aCr, rnd_aPr, rnd_bCf, rnd_bCr, rnd_bPr] = prepare_resampled_data(cfg, aCf, aCr, aPr, bCf, bCr, bPr);
    % concatenate the different resamplings
    Cf = cat(1, reshape(avg_aCf, [1 Nchans Nchans]), reshape(avg_bCf, [1 Nchans Nchans]), rnd_aCf, rnd_bCf);
    Cr = cat(1, reshape(avg_aCr, [1 Nchans 1     ]), reshape(avg_bCr, [1 Nchans 1     ]), rnd_aCr, rnd_bCr);
    Pr = cat(1, reshape(avg_aPr, [1 1      1     ]), reshape(avg_bPr, [1 1      1     ]), rnd_aPr, rnd_bPr);
    % clear temporary working copies
    clear avg_aCf avg_aCr avg_aPr avg_bCf avg_bCr avg_bPr
    clear rnd_aCf rnd_aCr rnd_aPr rnd_bCf rnd_bCr rnd_bPr
    % the order of the resamplings should be [avgA avgB rndA rndB rndA rndB rndA rndB ....]
    Nrepetitions = 2*cfg.numpermutation + 2;
    order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions];
    Cf = Cf(order,:,:);
    Cr = Cr(order,:,:);
    Pr = Pr(order,:,:);

  elseif strcmp(cfg.randomization, 'yes')
    % compute the cross-spectral density matrix without resampling
    [dum, avg_aCf, avg_aCr, avg_aPr, avg_bCf, avg_bCr, avg_bPr] = prepare_resampled_data(cfg2 , aCf, aCr, aPr, bCf, bCr, bPr);
    % compute the cross-spectral density matrix with random resampling
    [dum, rnd_aCf, rnd_aCr, rnd_aPr, rnd_bCf, rnd_bCr, rnd_bPr] = prepare_resampled_data(cfg, aCf, aCr, aPr, bCf, bCr, bPr);
    % concatenate the different resamplings
    Cf = cat(1, reshape(avg_aCf, [1 Nchans Nchans]), reshape(avg_bCf, [1 Nchans Nchans]), rnd_aCf, rnd_bCf);
    Cr = cat(1, reshape(avg_aCr, [1 Nchans 1     ]), reshape(avg_bCr, [1 Nchans 1     ]), rnd_aCr, rnd_bCr);
    Pr = cat(1, reshape(avg_aPr, [1 1      1     ]), reshape(avg_bPr, [1 1      1     ]), rnd_aPr, rnd_bPr);
    % clear temporary working copies
    clear avg_aCf avg_aCr avg_aPr avg_bCf avg_bCr avg_bPr
    clear rnd_aCf rnd_aCr rnd_aPr rnd_bCf rnd_bCr rnd_bPr
    % the order of the resamplings should be [avgA avgB rndA rndB rndA rndB rndA rndB ....]
    Nrepetitions = 2*cfg.numrandomization + 2;
    order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions];
    Cf = Cf(order,:,:);
    Cr = Cr(order,:,:);
    Pr = Pr(order,:,:);

  elseif strcmp(cfg.jackknife, 'yes')
    % compute the cross-spectral density matrix with jackknife resampling
    [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr);
    Nrepetitions = Ntrials;

  elseif strcmp(cfg.bootstrap, 'yes')
    % compute the cross-spectral density matrix with bootstrap resampling
    [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr);
    Nrepetitions = cfg.numbootstrap;

  elseif strcmp(cfg.pseudovalue, 'yes')
    % compute the cross-spectral density matrix with pseudovalue resampling
    [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr);
    Nrepetitions = Ntrials+1;

  elseif strcmp(cfg.singletrial, 'yes')
    % The idea is that beamformer uses the average covariance to construct the
    % filter and applies it to the single trial covariance/csd. The problem
    % is that beamformer will use the averaged covariance/csd to estimate the
    % power and not the single trial covariance/csd
    ft_error('this option contains a bug, and is therefore not supported at the moment');
    Cf = Cf; % FIXME, should be averaged and repeated for each trial
    Cr = Cr; % FIXME, should be averaged and repeated for each trial
    Pr = Pr; % FIXME, should be averaged and repeated for each trial
    Nrepetitions = Ntrials;

  elseif strcmp(cfg.rawtrial, 'yes')
    % keep all the individual trials, do not average them
    Cf = Cf;
    Cr = Cr;
    Pr = Pr;
    Nrepetitions = Ntrials;

  elseif Ntrials>1
    % compute the average from the individual trials
    Cf = reshape(sum(Cf, 1) / Ntrials, [Nchans Nchans]);
    Cr = reshape(sum(Cr, 1) / Ntrials, [Nchans 1]);
    Pr = reshape(sum(Pr, 1) / Ntrials, [1 1]);
    Nrepetitions = 1;

  elseif Ntrials==1
    % no rearrangement of trials is neccesary, the data already represents the average
    Cf = Cf;
    Cr = Cr;
    Pr = Pr;
    Nrepetitions = 1;
  end

  % reshape so that it also looks like one trial (out of many)
  if Nrepetitions==1
    Cf  = reshape(Cf , [1 Nchans Nchans]);
    Cr  = reshape(Cr , [1 Nchans 1]);
    Pr  = reshape(Pr , [1 1 1]);
  end

  % get the relevant low level options from the cfg and convert into key-value pairs
  tmpcfg = cfg.(cfg.method);
  % disable console feedback for the low-level function in case of multiple
  % repetitions
  if Nrepetitions > 1
    tmpcfg.feedback = 'none';
  end
  optarg = ft_cfg2keyval(tmpcfg);

  if Nrepetitions > 1
    ft_progress('init', cfg.(cfg.method).feedback, 'scanning repetition...');
  end

  for i=1:Nrepetitions
    size_Cf    = size(Cf);
    squeeze_Cf = reshape(Cf(i,:,:), size_Cf(2:end));

    if Nrepetitions > 1
      ft_progress(i/Nrepetitions, 'scanning repetition %d from %d', i, Nrepetitions);
    end

    switch cfg.method
      case 'dics'
        if strcmp(submethod, 'dics_power')
          dip(i) = beamformer_dics(sourcemodel, sens, headmodel, [],  squeeze_Cf, optarg{:});
        elseif strcmp(submethod, 'dics_refchan')
          dip(i) = beamformer_dics(sourcemodel, sens, headmodel, [],  squeeze_Cf, optarg{:}, 'Cr', Cr(i,:), 'Pr', Pr(i));
        elseif strcmp(submethod, 'dics_refdip')
          dip(i) = beamformer_dics(sourcemodel, sens, headmodel, [],  squeeze_Cf, optarg{:}, 'refdip', cfg.refdip);
        end
      case 'pcc'
        if ~isempty(avg) && istrue(cfg.rawtrial)
          % FIXME added by jansch because an appropriate subselection of avg
          % should be done first (i.e. select the tapers that belong to this
          % repetition
          ft_error('rawtrial in combination with pcc has been temporarily disabled');
        else
          dip(i) = beamformer_pcc(sourcemodel, sens, headmodel, avg, squeeze_Cf, optarg{:}, 'refdip', cfg.refdip, 'refchan', refchanindx, 'supdip', cfg.supdip, 'supchan', supchanindx);
        end
      case 'eloreta'
        dip(i) = ft_eloreta(sourcemodel, sens, headmodel, avg, squeeze_Cf, optarg{:});
      case 'mne'
        dip(i) = minimumnormestimate(sourcemodel, sens, headmodel, avg, optarg{:});
      case 'harmony'
        dip(i) = harmony(sourcemodel, sens, headmodel, avg, optarg{:});
        % ft_error(sprintf('method ''%s'' is unsupported for source reconstruction in the frequency domain', cfg.method));
      case {'rv'}
        dip(i) = residualvariance(sourcemodel, sens, headmodel, avg, optarg{:}) ;
      case {'music'}
        ft_error('method ''%s'' is currently unsupported for source reconstruction in the frequency domain', cfg.method);
      otherwise
    end

  end
  if Nrepetitions > 1
    ft_progress('close');
  end

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % do time domain source reconstruction
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif istimelock && any(strcmp(cfg.method, {'lcmv', 'sam', 'mne','harmony', 'rv', 'music', 'pcc', 'mvl', 'sloreta', 'eloreta'}))

  % determine the size of the data
  Nsamples = length(data.time);
  Nchans   = length(data.label);
  if isfield(data, 'cov') && length(size(data.cov))==3
    Ntrials = size(data.cov,1);
  elseif isfield(data, 'trial') && length(size(data.trial))==3
    Ntrials = size(data.trial,1);
  else
    Ntrials = 1;
  end

  if isfield(data, 'cov')
    % use the estimated data covariance matrix
    hascovariance = 1;
  else
    % add a identity covariance matrix, this simplifies the handling of the different source reconstruction methods
    % since the covariance is only used by some reconstruction methods and might not always be present in the data
    if Ntrials==1
      data.cov = eye(Nchans);
    else
      data.cov = zeros(Ntrials,Nchans,Nchans);
      for i=1:Ntrials
        data.cov(i,:,:) = eye(Nchans);
      end
    end
    hascovariance = 0;
    ft_warning('No covariance matrix found - will assume identity covariance matrix (mininum-norm solution)');
  end

  if strcmp(cfg.method, 'pcc')
    % HACK: requires some extra defaults
    if ~isfield(cfg, 'refdip'), cfg.refdip = []; end
    if ~isfield(cfg, 'supdip'), cfg.supdip = []; end

    % HACK: experimental code
    if hasbaseline
      ft_error('not supported')
    end

    tmpcfg = [];
    tmpcfg.channel = cfg.channel(:)';
    if isfield(cfg, 'refchan')
      tmpcfg.channel = [tmpcfg.channel cfg.refchan(:)'];
    end
    if isfield(cfg, 'supchan')
      tmpcfg.channel = [tmpcfg.channel cfg.supchan(:)'];
    end

    % select the data in the channels of interest
    [dum, datchanindx] = match_str(tmpcfg.channel, data.label);
    if Ntrials==1
      data.avg = data.avg(datchanindx,:);
      data.cov = data.cov(datchanindx,datchanindx);
    else
      data.cov   = data.cov(:,datchanindx,datchanindx);
      data.trial = data.trial(:,datchanindx,:);
    end
    data.label = data.label(datchanindx);

    if isfield(cfg, 'refchan') && ~isempty(cfg.refchan)
      [dum, refchanindx] = match_str(cfg.refchan, data.label);
    else
      refchanindx = [];
    end
    if isfield(cfg, 'supchan') && ~isempty(cfg.supchan)
      [dum, supchanindx] = match_str(cfg.supchan, data.label);
    else
      supchanindx = [];
    end
    Nchans = length(tmpcfg.channel); % update the number of channels

  else
    % HACK: use the default code
    % select the channels of interest
    [dum, datchanindx] = match_str(cfg.channel, data.label);
    if strcmp(data.dimord, 'chan_time')
      % It is in principle possible to have timelockanalysis with
      % keeptrial=yes and only a single trial in the raw data.
      % In that case the covariance should be represented as Nchan*Nchan
      data.avg = data.avg(datchanindx,:);
      %data.cov = reshape(data.cov, length(datchanindx), length(datchanindx));
      data.cov = data.cov(datchanindx,datchanindx);
    elseif strcmp(data.dimord, 'rpt_chan_time')
      data.cov   = data.cov(:,datchanindx,datchanindx);
      data.trial = data.trial(:,datchanindx,:);
    else
      ft_error('unexpected dimord');
    end
    data.label = data.label(datchanindx);
    Nchans     = length(data.label);
  end

  if hasbaseline
    % baseline and active are only available together for resampling purposes,
    % hence I assume here that there are multiple trials in both
    baseline.avg   = baseline.avg(datchanindx,:);
    baseline.cov   = baseline.cov(:,datchanindx,datchanindx);
    baseline.trial = baseline.trial(:,datchanindx,:);
    % this is required for averaging 2 conditions using prepare_resampled_data
    cfg2 = [];
    cfg2.numcondition = 2;
  end

  % prepare the resampling of the trials, or average the data if multiple trials are present and no resampling is necessary
  if (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes') || strcmp(cfg.randomization, 'yes')) && ~strcmp(data.dimord, 'rpt_chan_time')
    ft_error('multiple trials required in the data\n');

  elseif strcmp(cfg.permutation, 'yes')
    % compute the average and covariance without resampling
    [dum, avgA, covA, avgB, covB] = prepare_resampled_data(cfg2 , data.trial, data.cov, baseline.trial, baseline.cov);
    % compute the average and covariance with random permutation
    [cfg, avRA, coRA, avRB, coRB] = prepare_resampled_data(cfg, data.trial, data.cov, baseline.trial, baseline.cov);
    % concatenate the different resamplings
    avg = cat(1, reshape(avgA, [1 Nchans Nsamples]), reshape(avgB, [1 Nchans Nsamples]), avRA, avRB);
    Cy  = cat(1, reshape(covA, [1 Nchans Nchans  ]), reshape(covB, [1 Nchans Nchans  ]), coRA, coRB);
    % clear temporary working copies
    clear avgA avgB covA covB
    clear avRA avRB coRA coRB
    % the order of the resamplings should be [avgA avgB randA randB randA randB randA randB ....]
    Nrepetitions = 2*cfg.numpermutation + 2;
    order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions];
    avg = avg(order,:,:);
    Cy  = Cy (order,:,:);

  elseif strcmp(cfg.randomization, 'yes')
    % compute the average and covariance without resampling
    [dum, avgA, covA, avgB, covB] = prepare_resampled_data(cfg2 , data.trial, data.cov, baseline.trial, baseline.cov);
    % compute the average and covariance with random resampling
    [cfg, avRA, coRA, avRB, coRB] = prepare_resampled_data(cfg, data.trial, data.cov, baseline.trial, baseline.cov);
    % concatenate the different resamplings
    avg = cat(1, reshape(avgA, [1 Nchans Nsamples]), reshape(avgB, [1 Nchans Nsamples]), avRA, avRB);
    Cy  = cat(1, reshape(covA, [1 Nchans Nchans  ]), reshape(covB, [1 Nchans Nchans  ]), coRA, coRB);
    % clear temporary working copies
    clear avgA avgB covA covB
    clear avRA avRB coRA coRB
    % the order of the resamplings should be [avgA avgB randA randB randA randB randA randB ....]
    Nrepetitions = 2*cfg.numrandomization + 2;
    order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions];
    avg = avg(order,:,:);
    Cy  = Cy (order,:,:);

  elseif strcmp(cfg.jackknife, 'yes')
    % compute the jackknife repetitions for the average and covariance
    [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov);
    Nrepetitions = Ntrials;

  elseif strcmp(cfg.bootstrap, 'yes')
    % compute the bootstrap repetitions for the average and covariance
    [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov);
    Nrepetitions = cfg.numbootstrap;

  elseif strcmp(cfg.pseudovalue, 'yes')
    % compute the pseudovalue repetitions for the average and covariance
    [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov);
    Nrepetitions = Ntrials+1;

  elseif strcmp(cfg.singletrial, 'yes')
    % The idea is that beamformer uses the average covariance to construct the
    % filter and applies it to the single trial covariance/csd. The problem
    % is that beamformer will use the averaged covariance/csd to estimate the
    % power and not the single trial covariance/csd
    ft_error('this option contains a bug, and is therefore not supported at the moment');
    % average the single-trial covariance matrices
    Cy = mean(data.cov,1);
    % copy the average covariance matrix for every individual trial
    Cy = repmat(Cy, [Ntrials 1 1]);
    % keep the single-trial ERFs, rename them to avg for convenience
    avg = data.trial;
    Nrepetitions = Ntrials;

  elseif strcmp(cfg.rawtrial, 'yes')
    % do not do any resampling, keep the single-trial covariances
    Cy = data.cov;
    % do not do any resampling, keep the single-trial ERFs (rename them to avg for convenience)
    avg = data.trial;
    Nrepetitions = Ntrials;

  elseif Ntrials>1
    % average the single-trial covariance matrices
    Cy  = reshape(mean(data.cov,1), [Nchans Nchans]);
    % compute the average ERF
    avg = shiftdim(mean(data.trial,1),1);
    Nrepetitions = 1;

  elseif Ntrials==1
    % select the average covariance matrix
    Cy  = data.cov;
    % select the average ERF
    avg = data.avg;
    Nrepetitions = 1;
  end

  % reshape so that it also looks like one trial (out of many)
  if Nrepetitions==1
    Cy  = reshape(Cy , [1 Nchans Nchans]);
    avg = reshape(avg, [1 Nchans Nsamples]);
  end

  % get the relevant low level options from the cfg and convert into key-value pairs
  optarg = ft_cfg2keyval(getfield(cfg, cfg.method));

  % This is the place to check for the consistency of the channel order in
  % the pre-computed leadfields/spatial filters, and to correct for it, if
  % necessary. This pertains to bugs 1746 and 3029.
  if isfield(sourcemodel, 'label') && (isfield(sourcemodel, 'leadfield') || isfield(sourcemodel, 'filter'))
    % match the channels in the leadfields/filters with those in the data
    [i1, i2] = match_str(cfg.channel, sourcemodel.label);
    if ~isequal(i2(:), (1:numel(sourcemodel.label))')
      if isfield(sourcemodel, 'leadfield')
        fprintf('\n\nSubselecting/reordering the channels in the precomputed leadfields\n\n');
        inside_indx = find(sourcemodel.inside);
        for k = inside_indx(:)'
          sourcemodel.leadfield{k} = sourcemodel.leadfield{k}(i2, :);
        end
      end
      if isfield(sourcemodel, 'filter')
        fprintf('\n\nSubselecting/reordering the channels in the precomputed filters\n\n');
        inside_indx = find(sourcemodel.inside);
        for k = inside_indx(:)'
          sourcemodel.filter{k} = sourcemodel.filter{k}(:, i2);
        end
      end
      sourcemodel.label = sourcemodel.label(i2);
    end
    if ~isequal(i1(:), (1:numel(cfg.channel))')
      % this is not so easy to deal with, throw an error
      ft_error('There''s a mismatch between the number/order of channels in the data, with respect to the channels in the precomputed leadfield/filter. This is not easy to solve automatically. Please look into this.');
    end
  end

  size_avg = [size(avg) 1];
  size_Cy  = [size(Cy) 1];
  if strcmp(cfg.method, 'lcmv')% && ~isfield(sourcemodel, 'filter')
    for i = 1:Nrepetitions
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
      fprintf('scanning repetition %d\n', i);
      dip(i) = beamformer_lcmv(sourcemodel, sens, headmodel, squeeze_avg, squeeze_Cy, optarg{:});
    end

    % the following has been disabled since it turns out to be wrong (see
    % bugzilla bug 2395)
    %   elseif 0 && strcmp(cfg.method, 'lcmv')
    %     %don't loop over repetitions (slow), but reshape the input data to obtain single trial timecourses efficiently
    %     %in the presence of filters pre-computed on the average (or whatever)
    %     tmpdat = reshape(permute(avg,[2 3 1]),[size_avg(2) size_avg(3)*size_avg(1)]);
    %     tmpdip = beamformer_lcmv(sourcemodel, sens, headmodel, tmpdat, squeeze(mean(Cy,1)), optarg{:});
    %     tmpmom = tmpdip.mom{tmpdip.inside(1)};
    %     sizmom = size(tmpmom);
    %
    %     for i=1:length(tmpdip.inside)
    %       indx = tmpdip.inside(i);
    %       tmpdip.mom{indx} = permute(reshape(tmpdip.mom{indx}, [sizmom(1) size_avg(3) size_avg(1)]), [3 1 2]);
    %     end
    %     try, tmpdip = rmfield(tmpdip, 'pow'); end
    %     try, tmpdip = rmfield(tmpdip, 'cov'); end
    %     try, tmpdip = rmfield(tmpdip, 'noise'); end
    %     for i=1:Nrepetitions
    %       dip(i).pos     = tmpdip.pos;
    %       dip(i).inside  = tmpdip.inside;
    %       dip(i).outside = tmpdip.outside;
    %       dip(i).mom     = cell(1,size(tmpdip.pos,1));
    %       if isfield(tmpdip, 'ori')
    %         dip(i).ori   = cell(1,size(tmpdip.pos,1));
    %       end
    %       dip(i).cov     = cell(1,size(tmpdip.pos,1));
    %       dip(i).pow     = nan(size(tmpdip.pos,1),1);
    %       for ii=1:length(tmpdip.inside)
    %         indx             = tmpdip.inside(ii);
    %         tmpmom           = reshape(tmpdip.mom{indx}(i,:,:),[sizmom(1) size_avg(3)]);
    %         dip(i).mom{indx} = tmpmom;
    %         if isfield(tmpdip, 'ori')
    %           dip(i).ori{indx} = tmpdip.ori{indx};
    %         end
    %
    %         % the following recovers the single trial power and covariance, but
    %         % importantly the latency over which the power is defined is the
    %         % latency of the event-related field in the input and not the
    %         % latency of the covariance window, which can differ from the
    %         % former
    %         dip(i).cov{indx} = (tmpmom*tmpmom')./size_avg(3);
    %         if isempty(cfg.lcmv.powmethod) || strcmp(cfg.lcmv.powmethod, 'trace')
    %           dip(i).pow(indx) = trace(dip(i).cov{indx});
    %         else
    %           [tmpu,tmps,tmpv] = svd(dip(i).cov{indx});
    %           dip(i).pow(indx) = tmps(1);
    %         end
    %       end
    %     end

  elseif strcmp(cfg.method, 'sloreta')
    for i=1:Nrepetitions
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
      fprintf('scanning repetition %d\n', i);
      dip(i) = ft_sloreta(sourcemodel, sens, headmodel, squeeze_avg, squeeze_Cy, optarg{:});
    end

  elseif strcmp(cfg.method, 'eloreta')
    for i=1:Nrepetitions
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
      fprintf('scanning repetition %d\n', i);
      dip(i) = ft_eloreta(sourcemodel, sens, headmodel, squeeze_avg, squeeze_Cy, optarg{:});
    end
  elseif strcmp(cfg.method, 'sam')
    for i=1:Nrepetitions
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
      fprintf('scanning repetition %d\n', i);
      squeeze_avg=reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      dip(i) = beamformer_sam(sourcemodel, sens, headmodel, squeeze_avg, squeeze_Cy, optarg{:});
    end
  elseif strcmp(cfg.method, 'pcc')
    for i=1:Nrepetitions
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
      fprintf('scanning repetition %d\n', i);
      squeeze_avg=reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      dip(i) = beamformer_pcc(sourcemodel, sens, headmodel, squeeze_avg, squeeze_Cy, optarg{:}, 'refdip', cfg.refdip, 'refchan', refchanindx, 'supchan', supchanindx);
    end
  elseif strcmp(cfg.method, 'mne')
    for i=1:Nrepetitions
      fprintf('estimating current density distribution for repetition %d\n', i);
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      if hascovariance
        squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
        dip(i) = minimumnormestimate(sourcemodel, sens, headmodel, squeeze_avg, optarg{:}, 'noisecov', squeeze_Cy);
      else
        dip(i) = minimumnormestimate(sourcemodel, sens, headmodel, squeeze_avg, optarg{:});
      end
    end
  elseif strcmp(cfg.method, 'harmony')
    for i=1:Nrepetitions
      fprintf('estimating current density distribution for repetition %d\n', i);
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      if hascovariance
        squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
        dip(i) = harmony(sourcemodel, sens, headmodel, squeeze_avg, optarg{:}, 'noisecov', squeeze_Cy);
      else
        dip(i) = harmony(sourcemodel, sens, headmodel, squeeze_avg, optarg{:});
      end
    end
  elseif strcmp(cfg.method, 'rv')
    for i=1:Nrepetitions
      fprintf('estimating residual variance at each source position for repetition %d\n', i);
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      dip(i) = residualvariance(sourcemodel, sens, headmodel, squeeze_avg,      optarg{:});
    end
  elseif strcmp(cfg.method, 'music')
    for i=1:Nrepetitions
      fprintf('computing multiple signal classification for repetition %d\n', i);
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      if hascovariance
        squeeze_Cy  = reshape(Cy(i,:,:), [size_Cy(2)  size_Cy(3)]);
        dip(i) = music(sourcemodel, sens, headmodel, squeeze_avg, 'cov', squeeze_Cy, optarg{:});
      else
        dip(i) = music(sourcemodel, sens, headmodel, squeeze_avg,                    optarg{:});
      end
    end
  elseif strcmp(cfg.method, 'mvl')
    for i=1:Nrepetitions
      fprintf('estimating current density distribution for repetition %d\n', i);
      fns = fieldnames(cfg);
      optarg = cell(1,length(fns));
      n=1;
      for c=1:length(fns)
        optarg{n} = fns{c};
        optarg{n+1} = cfg.(fns{c});
        n=n+2;
      end
      squeeze_avg = reshape(avg(i,:,:),[size_avg(2) size_avg(3)]);
      dip(i) = mvlestimate(sourcemodel, sens, headmodel, squeeze_avg, optarg{:});
    end
  else
    ft_error('method ''%s'' is unsupported for source reconstruction in the time domain', cfg.method);
  end

elseif iscomp
  ft_error('the use of component data in ft_sourceanalysis is disabled for the time being: if you encounter this error message and you need this functionality please contact the FieldTrip development team');
else
  ft_error('the specified method ''%s'' combined with the input data of type ''%s'' are not supported', cfg.method, ft_datatype(data));
end % if freq or timelock or comp data

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% clean up and collect the results
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

source = copyfields(sourcemodel, source, {'pos', 'tri', 'dim', 'inside', 'leadfield', 'leadfielddimord', 'label'}); %, 'filter'});

if exist('dip', 'var')
  % the fields in the dip structure might be more recent than those in the sourcemodel structure
  source = copyfields(dip, source, {'pos', 'inside', 'leadfield', 'leadfielddimord', 'label'}); %, 'filter'});

  % prevent duplication of these fields when copying the content of dip into source.avg or source.trial
  dip    = removefields(dip,       {'pos', 'inside', 'leadfield', 'leadfielddimord', 'label'}); %, 'filter'});

  if istrue(cfg.(cfg.method).keepfilter) && isfield(dip(1), 'filter')
    for k = 1:numel(dip)
      dip(k).label        = sens.label;
      dip(k).filterdimord = '{pos}_ori_chan';
    end
  end
end

if ~istrue(cfg.keepleadfield)
  % remove the precomputed leadfields from the output source (if present)
  source = removefields(source, {'leadfield' 'leadfielddimord' 'label'});
end

% remove the precomputed leadfields from the cfg regardless of what keepleadfield is saying
% it should not be kept in cfg, since there it takes up too much space
cfg.sourcemodel = removefields(cfg.sourcemodel, {'leadfield' 'leadfielddimord' 'filter' 'filterdimord' 'label'});

if strcmp(cfg.jackknife, 'yes')
  source.method = 'jackknife';
  source.trial = dip;
  source.df = Ntrials;
elseif strcmp(cfg.bootstrap, 'yes')
  source.method = 'bootstrap';
  source.trial = dip;
  source.df = Ntrials;
elseif strcmp(cfg.pseudovalue, 'yes')
  source.method = 'pseudovalue';
  source.trial = dip;
elseif strcmp(cfg.singletrial, 'yes')
  source.method = 'singletrial';
  source.trial = dip;
  source.df = Ntrials;     % is this correct?
elseif strcmp(cfg.rawtrial, 'yes')
  source.method = 'rawtrial';
  source.trial = dip;
  source.df = Ntrials;     % is this correct?
elseif strcmp(cfg.randomization, 'yes')
  % assign the randomized resamplings to the output, keeping the special meaning of trial 1 and 2 in mind
  source.method = 'randomization';
  source.avgA = dip(1);
  source.avgB = dip(2);
  source.trialA = dip(1+2*(1:cfg.numrandomization));
  source.trialB = dip(2+2*(1:cfg.numrandomization));
elseif strcmp(cfg.permutation, 'yes')
  % assign the randomized resamplings to the output, keeping the special meaning of trial 1 and 2 in mind
  source.method = 'permutation';
  source.avgA = dip(1);
  source.avgB = dip(2);
  source.trialA = dip(1+2*(1:cfg.numpermutation));
  source.trialB = dip(2+2*(1:cfg.numpermutation));
elseif (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes')) && strcmp(cfg.keeptrials, 'yes')
  % keep the source reconstruction for each repeated or resampled trial
  source.trial = dip;
elseif exist('dip', 'var')
  % it looks like beamformer analysis was done on an average input, keep the average source reconstruction
  source.method = 'average';
  source.avg = dip;
else
  % apparently no computations were performed
end

% remember the trialinfo
if (strcmp(cfg.keeptrials, 'yes') || strcmp(cfg.method, 'pcc')) && isfield(data, 'trialinfo')
  source.trialinfo = data.trialinfo;
end

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble trackconfig
ft_postamble previous   data baseline
ft_postamble provenance source
ft_postamble history    source
ft_postamble savevar    source


function pot = convert_to_pot(CPD, pot_type, domain, evidence)
% CONVERT_TO_POT Convert a root CPD to one or more potentials
% pots = convert_to_pot(CPD, pot_type, domain, evidence)

assert(length(domain)==1);
assert(~isempty(evidence(domain)));
T = 1;

sz = CPD.sizes;
ns = zeros(1, max(domain));
ns(domain) = sz;

switch pot_type
 case 'u',
  pot = upot(domain, 1, T, 0);
 case 'd',
  ns(domain) = 1;
  pot = dpot(domain, ns(domain), T);
 case {'c','g'},
  ns(domain) = 0;
  pot = cpot(domain, ns(domain), 0);
 case 'cg',
  ddom = [];
  cdom = domain; % we assume the root node is cts
  %pot = cgpot(ddom, cdom, ns, {cpot([],[],0)});
  pot = cgpot(ddom, cdom, ns);
end


% -*- INTERNAL UNDOCUMENTED FUNCTION -*-
function [geometry, msh, space, u] = ...
              solve_laplace_3d_iso (problem_data, method_data)

warning ('geopdes:obsolete', 'Function SOLVE_LAPLACE_3D_ISO is obsolete. Using SOLVE_LAPLACE_ISO instead')

[geometry, msh, space, u] = solve_laplace_iso (problem_data, method_data);


function launcher(alignmentType)
% clc; clear; close all
addpath(genpath('thirdparty'));

%%
if ~exist('alignmentType','var')
    alignmentType = 1; %0 for nowarp, 1 for optical flow, 2 for homography, 3 for similarity
end
path2dataset = '../dataset/qualitative_datasets';

%%
datasets = dir(path2dataset);
dirFlags = [datasets.isdir];
datasets(~dirFlags) = [];
datasets = {datasets(3:end).name};

% permute and divide into training and testing sets
num_datasets = numel(datasets);
seed = 12;
rng(seed);
ds_idx = randperm(num_datasets);

alignment = '';
if alignmentType == 0
    alignment = '_nowarp';
elseif alignmentType == 1
    alignment = '_OF';
elseif alignmentType == 2
    alignment = '_homography';
end

path2output = @(stage,d) sprintf('../data/testing_real_all_nostab%s/%s/image_%s',alignment,stage,d);

fn_in = @(dsi,type,fri) [path2dataset '/' datasets{ds_idx(dsi)} '/' type '/' sprintf('%05d.jpg',fri)];
fn_out = @(stage,fri,frid) sprintf('%s/%05d.jpg',path2output(stage,frid),fri);

ds_range = 1:num_datasets;

for l = -2:2
    for i = 1:num_datasets
        checkDir(path2output(datasets{i},num2str(l)));
    end
end

%%
for ii = 1:length(ds_range)
    fr_cnt = 0;
    i = ds_range(ii);
    % get the frame range
    datasets{ds_idx(i)}
    files = dir([path2dataset '/' datasets{ds_idx(i)} '/input/*.jpg']);
    if isempty(files)
        files = dir([path2dataset '/' datasets{ds_idx(i)} '/input/*.png']);
    end
    if ~isempty(files)
        [~,ststr,~] = fileparts(files(1).name);
        [~,enstr,~] = fileparts(files(end).name);
        start_frame = str2num(ststr);
        end_frame = str2num(enstr);
        frame_range = start_frame:min(start_frame+99,end_frame);
        num_frame = numel(frame_range);

        fr_idx = floor(linspace(frame_range(1),frame_range(end),num_frame));
        for j = 1:num_frame
            fr_cnt = fr_cnt+1;
            % save image_1 to image_5
            v0 = im2double(imread(fn_in(i,'input',fr_idx(j)+0)));
            v0g = single(rgb2gray(v0));
            [h,w,~] = size(v0);

            for l = -2:2
                if l ~= 0
                    vi = im2double(imread(fn_in(i,'input',max(min(fr_idx(j)+l,frame_range(end)),frame_range(1)))));
                    vig = single(rgb2gray(vi));
                    if alignmentType == 0
                        v_i0 = vi;
                    elseif alignmentType == 1
                        flo_i0 = genFlow(v0g, vig);
                        [v_i0, ~] = warpToRef(v0, vi, flo_i0);
                    elseif alignmentType == 2
                        v_i0 = homographyAlignment(v0,vi,0);
                    elseif alignmentType == 3
                        v_i0 = similarityAlignment(v0,vi,0);
                    end
                else
                    v_i0 = v0;
                end
                imwrite(v_i0, fn_out(datasets{ds_idx(i)},fr_cnt,num2str(l)));
            end
        end
    end
end


function [] = writefort11( fort11dat, finame )
%
%

if ( nargin == 1 )
  finputname = 'fort.11_1' ;
else
  finputname = finame ;
end

fid = fopen(finputname,'w') ;

fprintf( fid, '%s\n', fort11dat.DataTitle ) ;
%fprintf( fid, '%s\n', fort11dat.DataSubTitle ) ;
fprintf( fid, '%d\n', fort11dat.DTIMINC ) ;

fprintf( fid, '%d\n', fort11dat.NumOfNodes ) ;

if iscell(fort11dat.Val)
    ValL = length(fort11dat.Val);
    valpernode = size(fort11dat.Val{1},1);
else
    % Write user-defined values
    [valpernode,~,ValL] = size( fort11dat.Val ) ;
end

% Looping over the number of times
for t = 1:ValL

    if iscell(fort11dat.Val)
        val = fort11dat.Val{t};
    else
        val = fort11dat.Val(:,:,t) ;
    end
    % Get a proper format
    str = '%d' ;
    for ll = 1: valpernode - 1
        str = [str ' %15.9e'] ;
    end
    str = [str '\n' ] ;

    fprintf( fid, str, val ) ;
end

fclose(fid) ;
%EOF
end


function drawSecPot(dietPath, rxnmax, startMet, levels, cutoff)
% Draws part of the community structure when maximized with the given
% reaction
%
% INPUTS:
%	dietPath          char with path of the model
%   rxnmax            char with name of the rxn that gets maximized with fastFVA
%   startMet          char with starting metabolite for visualizing
%   levels            number with levels that are connected to the starting
%                     metabolite
%   cutoff            number of fluxes that are considered for drawing,
%                     only fluxes>abs(cutoff) are considered

global CBT_LP_SOLVER
if isempty(CBT_LP_SOLVER)
    initCobraToolbox
end

microbiota_model=load(dietPath);
modelF=fieldnames(microbiota_model);
model=microbiota_model.(modelF{1});

% parameters for fastFVA
cpxControl.PARALLELMODE = 1;
cpxControl.THREADS = 1;
cpxControl.AUXROOTTHREADS = 2;

% calculating max secretion potential
%(note: if diet constraint present max. secretion flux = max(EX_rxn[fe]) - min(EX_rxn[d]))
[minFlux, maxFlux, optsol, ret, fbasol, fvamin, fvamax]  = fastFVA(model,99.99,'max',{},rxnmax,'A',cpxControl);

% all the metabolites and reactions connected to the starting
startMetnr = find(string(model.mets) == char(startMet));

[a,b] = inorder(startMetnr, model, [], [], levels(1));

% names of the reactions that are of interest
rxoi = model.rxns(b);

%  filter reactions and fluxes that are greater than abs(cutoff)
rxngz = [];
flxgz = [];
n = length(rxoi)
for i=1:n
    progress = i/n;
    sprintf('Progress %f ', progress)
    if(abs(fvamax(find(string(model.rxns)== char(rxoi(i)), 1))) > cutoff)
        rxngz = [rxngz, rxoi(i)];
        %flxgz = [flxgz, fvamax(find(string(model.rxns)== char(rxoi(i)), 1))];
    end
end

%flxgz = flxgz';

diffmets = setdiff(model.mets, model.mets(a));
[Involved_mets, Dead_ends] = draw_by_rxn(model, rxngz, 'true', 'struc', {''}, diffmets, fvamax);


addpath("utils\")

config202107311 % config file

n = 100; % run n times
result = zeros(n, 4);

for i = 1:n
    clc
    disp(['i = ' num2str(i)]);
    [result(i,1:2), result(i,3:4)]= wheelslam_func(paras);

end

path   = paras.datapath;
%write_bin([path 'finalresults_' num2str(paras.NPARTICLES) '.bin'], result);

% fp_res  = fopen([path 'finalresultsall.txt'],'a+');
% s_curt  = datestr(now);
% format longG
% fprintf(fp_res,'%s\n', s_curt);
% fprintf(fp_res,'Particles = %d NEFFECTIVE = %d\n', paras.NPARTICLES, paras.NEFFECTIVE);
% fprintf(fp_res,'Gridlen = %.1f mode = %d\n', paras.gridlen, paras.mode);
% fprintf(fp_res,'Disstd    = %.5f  Phistd  = %.5f \n', paras.sigmaDis_scale, paras.sigmaPhi);
% fprintf(fp_res,'RollSampleDis = %.1f    RollSeqDim = %d\n', paras.sampleDis, paras.rollSeqdimension);
% fprintf(fp_res,'RollSeqWindow = %d  CorrCoefThr = %.1f  CorrCoefNumThr = %d\n',paras.conRevisitNumThr,paras.corrCoefThr,paras.corrCoefNumThr);
%
% fprintf(fp_res,'%s\n', 'Mean          [Hor. pos.     heading]');
% fprintf(fp_res,'Wheel-SLAM       %.2f          %.2f\n', mean(result(1:i,1)), mean(result(1:i,2)));
% fprintf(fp_res,'Wheel-INS       %.2f        %.2f\n\n', result(1,3), result(1,4));

figure,
subplot(2,1,1),
plot(result(1:i,3), 'LineWidth', 1.5);hold on;plot(result(1:i,1), 'LineWidth', 1.5);
title([num2str(paras.experiencetime) '-' num2str(paras.experiencenum)]);
ylabel('Hor. RMSE(m)'), xlabel('Test No.');box on, grid on;
legend('Wheel-INS','Wheel-SLAM');
set(gca,'fontsize',10,'fontname','Times');
subplot(2,1,2),
plot(result(1:i,4), 'LineWidth', 1.5);hold on;plot(result(1:i,2), 'LineWidth', 1.5);
ylabel('Heading RMSE(deg)'), xlabel('Test No.');box on, grid on;
set(gca,'fontsize',10,'fontname','Times');


function test_bug1298

% MEM 3gb
% WALLTIME 00:10:00
% DEPENDENCY ft_timelockanalysis ft_prepare_leadfield ft_sourceanalysis

megraw = load(dccnpath('/home/common/matlab/fieldtrip/data/ftp/tutorial/beamformer/data_all.mat'));

cfg = [];
cfg.covariance = 'yes';
cfg.keeptrials = 'yes';
megtlock = ft_timelockanalysis(cfg,megraw.data_all);

load(dccnpath('/home/common/matlab/fieldtrip/data/test/latest/vol/Subject01vol_localspheres.mat'))

cfg = [];
cfg.headmodel = vol;
grid = ft_prepare_leadfield(cfg,megtlock);

cfg = [];
cfg.headmodel = vol;
cfg.method = 'lcmv';
cfg.sourcemodel = grid;
cfg.keepleadfield = 'yes';
cfg.lcmv.keepfilter = 'yes';
megsource1 = ft_sourceanalysis(cfg,megtlock);

cfg = [];
cfg.headmodel = vol;
cfg.method = 'lcmv';
cfg.sourcemodel = grid;
cfg.sourcemodel.leadfield = megsource1.leadfield;
cfg.sourcemodel.filter = megsource1.avg.filter;
% cfg.keeptrials = 'yes';
cfg.rawtrial = 'yes';
megsource11 = ft_sourceanalysis(cfg,megtlock);

% and then single trial estimates are in megsource11.trial


function [info, str] = our_vl_simplenn_display(net, varargin)
%VL_SIMPLENN_DISPLAY  Display the structure of a SimpleNN network.
%   VL_SIMPLENN_DISPLAY(NET) prints statistics about the network NET.
%
%   INFO = VL_SIMPLENN_DISPLAY(NET) returns instead a structure INFO
%   with several statistics for each layer of the network NET.
%
%   [INFO, STR] = VL_SIMPLENN_DISPLAY(...) returns also a string STR
%   with the text that would otherwise be printed.
%
%   The function accepts the following options:
%
%   `inputSize`:: auto
%      Specifies the size of the input tensor X that will be passed to
%      the network as input. This information is used in order to
%      estiamte the memory required to process the network. When this
%      option is not used, VL_SIMPLENN_DISPLAY() tires to use values
%      in the NET structure to guess the input size:
%      NET.META.INPUTSIZE and NET.META.NORMALIZATION.IMAGESIZE
%      (assuming a batch size of one image, unless otherwise specified
%      by the `batchSize` option).
%
%   `batchSize`:: []
%      Specifies the number of data points in a batch in estimating
%      the memory consumption, overriding the last dimension of
%      `inputSize`.
%
%   `maxNumColumns`:: 18
%      Maximum number of columns in a table. Wider tables are broken
%      into multiple smaller ones.
%
%   `format`:: `'ascii'`
%      One of `'ascii'`, `'latex'`, or `'csv'`.
%
%   See also: VL_SIMPLENN().

% Copyright (C) 2014-15 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

opts.inputSize = [] ;
opts.batchSize = [] ;
opts.maxNumColumns = 18 ;
opts.format = 'ascii' ;
opts = vl_argparse(opts, varargin) ;

% determine input size, using first the option, then net.meta.inputSize,
% and eventually net.meta.normalization.imageSize, if any
if isempty(opts.inputSize)
  tmp = [] ;
  opts.inputSize = [NaN;NaN;NaN;1] ;
  if isfield(net, 'meta')
    if isfield(net.meta, 'inputSize')
      tmp =  net.meta.inputSize(:) ;
    elseif isfield(net.meta, 'normalization') && ...
        isfield(net.meta.normalization, 'imageSize')
      tmp = net.meta.normalization.imageSize ;
    end
    opts.inputSize(1:numel(tmp)) = tmp(:) ;
  end
end

if ~isempty(opts.batchSize)
  opts.inputSize(4) = opts.batchSize ;
end

fields={'layer', 'type', 'name', '-', ...
        'support', 'filtd', 'filtdil', 'nfilt', 'stride', 'pad', '-', ...
        'rfsize', 'rfoffset', 'rfstride', '-', ...
        'dsize', 'ddepth', 'dnum', '-', ...
        'xmem', 'wmem'};

% get the support, stride, and padding of the operators
for l = 1:numel(net.layers)
  ly = net.layers{l} ;
  switch ly.type
    case {'conv','conv_mask'}
      ks = max([size(ly.weights{1},1) ; size(ly.weights{1},2)],1) ;
      ks = (ks - 1) .* ly.dilate + 1 ;
      info.support(1:2,l) = ks ;
    case 'pool'
      info.support(1:2,l) = ly.pool(:) ;
    otherwise
      info.support(1:2,l) = [1;1] ;
  end
  if isfield(ly, 'stride')
    info.stride(1:2,l) = ly.stride(:) ;
  else
    info.stride(1:2,l) = 1 ;
  end
  if isfield(ly, 'pad')
    info.pad(1:4,l) = ly.pad(:) ;
  else
    info.pad(1:4,l) = 0 ;
  end

  % operator applied to the input image
  info.receptiveFieldSize(1:2,l) = 1 + ...
      sum(cumprod([[1;1], info.stride(1:2,1:l-1)],2) .* ...
          (info.support(1:2,1:l)-1),2) ;
  info.receptiveFieldOffset(1:2,l) = 1 + ...
      sum(cumprod([[1;1], info.stride(1:2,1:l-1)],2) .* ...
          ((info.support(1:2,1:l)-1)/2 - info.pad([1 3],1:l)),2) ;
  info.receptiveFieldStride = cumprod(info.stride,2) ;
end

% get the dimensions of the data
info.dataSize(1:4,1) = opts.inputSize(:) ;
for l = 1:numel(net.layers)
  ly = net.layers{l} ;
  if strcmp(ly.type, 'custom') && isfield(ly, 'getForwardSize')
    sz = ly.getForwardSize(ly, info.dataSize(:,l)) ;
    info.dataSize(:,l+1) = sz(:) ;
    continue ;
  end

  info.dataSize(1, l+1) = floor((info.dataSize(1,l) + ...
                                 sum(info.pad(1:2,l)) - ...
                                 info.support(1,l)) / info.stride(1,l)) + 1 ;
  info.dataSize(2, l+1) = floor((info.dataSize(2,l) + ...
                                 sum(info.pad(3:4,l)) - ...
                                 info.support(2,l)) / info.stride(2,l)) + 1 ;
  info.dataSize(3, l+1) = info.dataSize(3,l) ;
  info.dataSize(4, l+1) = info.dataSize(4,l) ;
  switch ly.type
    case 'conv'
      if isfield(ly, 'weights')
        f = ly.weights{1} ;
      else
        f = ly.filters ;
      end
      if size(f, 3) ~= 0
        info.dataSize(3, l+1) = size(f,4) ;
      end
    case {'loss', 'softmaxloss'}
      info.dataSize(3:4, l+1) = 1 ;
    case 'custom'
      info.dataSize(3,l+1) = NaN ;
  end
end

if nargout == 1, return ; end

% print table
table = {} ;
wmem = 0 ;
xmem = 0 ;
for wi=1:numel(fields)
  w = fields{wi} ;
  switch w
    case 'type', s = 'type' ;
    case 'stride', s = 'stride' ;
    case 'rfsize', s = 'rf size' ;
    case 'rfstride', s = 'rf stride' ;
    case 'rfoffset', s = 'rf offset' ;
    case 'dsize', s = 'data size' ;
    case 'ddepth', s = 'data depth' ;
    case 'dnum', s = 'data num' ;
    case 'nfilt', s = 'num filts' ;
    case 'filtd', s = 'filt dim' ;
    case 'filtdil', s = 'filt dilat' ;
    case 'wmem', s = 'param mem' ;
    case 'xmem', s = 'data mem' ;
    otherwise, s = char(w) ;
  end
  table{wi,1} = s ;

  % do input pseudo-layer
  for l=0:numel(net.layers)
    switch char(w)
      case '-', s='-' ;
      case 'layer', s=sprintf('%d', l) ;
      case 'dsize', s=pdims(info.dataSize(1:2,l+1)) ;
      case 'ddepth', s=sprintf('%d', info.dataSize(3,l+1)) ;
      case 'dnum', s=sprintf('%d', info.dataSize(4,l+1)) ;
      case 'xmem'
        a = prod(info.dataSize(:,l+1)) * 4 ;
        s = pmem(a) ;
        xmem = xmem + a ;
      otherwise
        if l == 0
          if strcmp(char(w),'type'), s = 'input';
          else s = 'n/a' ; end
        else
          ly=net.layers{l} ;
          switch char(w)
            case 'name'
              if isfield(ly, 'name')
                s=ly.name ;
              else
                s='' ;
              end
            case 'type'
              switch ly.type
                case 'normalize', s='norm';
                case 'pool'
                  if strcmpi(ly.method,'avg'), s='apool'; else s='mpool'; end
                case 'softmax', s='softmx' ;
                case 'softmaxloss', s='softmxl' ;
                otherwise s=ly.type ;
              end
            case 'nfilt'
              switch ly.type
                case 'conv'
                  if isfield(ly, 'weights'), a = size(ly.weights{1},4) ;
                  else, a = size(ly.filters,4) ; end
                  s=sprintf('%d',a) ;
                otherwise
                  s='n/a' ;
              end
            case 'filtd'
              switch ly.type
                case 'conv'
                  s=sprintf('%d',size(ly.weights{1},3)) ;
                otherwise
                  s='n/a' ;
              end
            case 'filtdil'
              switch ly.type
                case 'conv'
                  s=sprintf('%d',ly.dilate) ;
                otherwise
                  s='n/a' ;
              end

            case 'support'
              s = pdims(info.support(:,l)) ;
            case 'stride'
              s = pdims(info.stride(:,l)) ;
            case 'pad'
              s = pdims(info.pad(:,l)) ;
            case 'rfsize'
              s = pdims(info.receptiveFieldSize(:,l)) ;
            case 'rfoffset'
              s = pdims(info.receptiveFieldOffset(:,l)) ;
            case 'rfstride'
              s = pdims(info.receptiveFieldStride(:,l)) ;

            case 'wmem'
              a = 0 ;
              if isfield(ly, 'weights') ;
                for j=1:numel(ly.weights)
                  a = a + numel(ly.weights{j}) * 4 ;
                end
              end
              % Legacy code to be removed
              if isfield(ly, 'filters') ;
                a = a + numel(ly.filters) * 4 ;
              end
              if isfield(ly, 'biases') ;
                a = a + numel(ly.biases) * 4 ;
              end
              s = pmem(a) ;
              wmem = wmem + a ;
          end
        end
    end
    table{wi,l+2} = s ;
  end
end

str = {} ;
for i=2:opts.maxNumColumns:size(table,2)
  sel = i:min(i+opts.maxNumColumns-1,size(table,2)) ;
  str{end+1} = ptable(opts, table(:,[1 sel])) ;
end

table = {...
  'parameter memory', sprintf('%s (%.2g parameters)', pmem(wmem), wmem/4);
  'data memory', sprintf('%s (for batch size %d)', pmem(xmem), info.dataSize(4,1))} ;
str{end+1} = ptable(opts, table) ;

str = horzcat(str{:}) ;

if nargout == 0
  fprintf('%s', str) ;
  clear info str ;
end

% -------------------------------------------------------------------------
function str = ptable(opts, table)
% -------------------------------------------------------------------------
switch opts.format
  case 'ascii', str = pascii(table) ;
  case 'latex', str = platex(table) ;
  case 'csv',   str = pcsv(table) ;
end
str = horzcat(str,sprintf('\n')) ;

% -------------------------------------------------------------------------
function s = pmem(x)
% -------------------------------------------------------------------------
if isnan(x),       s = 'NaN' ;
elseif x < 1024^1, s = sprintf('%.0fB', x) ;
elseif x < 1024^2, s = sprintf('%.0fKB', x / 1024) ;
elseif x < 1024^3, s = sprintf('%.0fMB', x / 1024^2) ;
else               s = sprintf('%.0fGB', x / 1024^3) ;
end

% -------------------------------------------------------------------------
function s = pdims(x)
% -------------------------------------------------------------------------
if all(x==x(1))
  s = sprintf('%.4g', x(1)) ;
else
  s = sprintf('%.4gx', x(:)) ;
  s(end) = [] ;
end

% -------------------------------------------------------------------------
function str = pascii(table)
% -------------------------------------------------------------------------
str = {} ;
sizes = max(cellfun(@(x) numel(x), table),[],1) ;
for i=1:size(table,1)
  for j=1:size(table,2)
    s = table{i,j} ;
    fmt = sprintf('%%%ds|', sizes(j)) ;
    if isequal(s,'-'), s=repmat('-', 1, sizes(j)) ; end
    str{end+1} = sprintf(fmt, s) ;
  end
  str{end+1} = sprintf('\n') ;
end
str = horzcat(str{:}) ;

% -------------------------------------------------------------------------
function str = pcsv(table)
% -------------------------------------------------------------------------
str = {} ;
sizes = max(cellfun(@(x) numel(x), table),[],1) + 2 ;
for i=1:size(table,1)
  if isequal(table{i,1},'-'), continue ; end
  for j=1:size(table,2)
    s = table{i,j} ;
    str{end+1} = sprintf('%s,', ['"' s '"']) ;
  end
  str{end+1} = sprintf('\n') ;
end
str = horzcat(str{:}) ;

% -------------------------------------------------------------------------
function str = platex(table)
% -------------------------------------------------------------------------
str = {} ;
sizes = max(cellfun(@(x) numel(x), table),[],1) ;
str{end+1} = sprintf('\\begin{tabular}{%s}\n', repmat('c', 1, numel(sizes))) ;
for i=1:size(table,1)
  if isequal(table{i,1},'-'), str{end+1} = sprintf('\\hline\n') ; continue ; end
  for j=1:size(table,2)
    s = table{i,j} ;
    fmt = sprintf('%%%ds', sizes(j)) ;
    str{end+1} = sprintf(fmt, latexesc(s)) ;
    if j<size(table,2), str{end+1} = sprintf('&') ; end
  end
  str{end+1} = sprintf('\\\\\n') ;
end
str{end+1} = sprintf('\\end{tabular}\n') ;
str = horzcat(str{:}) ;

% -------------------------------------------------------------------------
function s = latexesc(s)
% -------------------------------------------------------------------------
s = strrep(s,'\','\\') ;
s = strrep(s,'_','\char`_') ;

% -------------------------------------------------------------------------
function [cpuMem,gpuMem] = xmem(s, cpuMem, gpuMem)
% -------------------------------------------------------------------------
if nargin <= 1
  cpuMem = 0 ;
  gpuMem = 0 ;
end
if isstruct(s)
  for f=fieldnames(s)'
    f = char(f) ;
    for i=1:numel(s)
      [cpuMem,gpuMem] = xmem(s(i).(f), cpuMem, gpuMem) ;
    end
  end
elseif iscell(s)
  for i=1:numel(s)
    [cpuMem,gpuMem] = xmem(s{i}, cpuMem, gpuMem) ;
  end
elseif isnumeric(s)
  if isa(s, 'single')
    mult = 4 ;
  else
    mult = 8 ;
  end
  if isa(s,'gpuArray')
    gpuMem = gpuMem + mult * numel(s) ;
  else
    cpuMem = cpuMem + mult * numel(s) ;
  end
end


function truefalse = ch_is_format_code ( c )

%*****************************************************************************80
%
%% CH_IS_FORMAT_CODE returns TRUE if a character is a FORTRAN format code.
%
%  Discussion:
%
%    The format codes accepted here are not the only legal format
%    codes in FORTRAN90.  However, they are more than sufficient
%    for my needs!
%
%  Table:
%
%    A  Character
%    B  Binary digits
%    D  Real number, exponential representation
%    E  Real number, exponential representation
%    F  Real number, fixed point
%    G  General format
%    I  Integer
%    L  Logical variable
%    O  Octal digits
%    Z  Hexadecimal digits
%    *  Free format
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 November 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character C, the character to be analyzed.
%
%    Output, logical TRUEFALSE, is TRUE (1) if C is a FORTRAN format code
%     and FALSE (0) otherwise.
%
  FALSE = 0;
  TRUE = 1;

      if ( ch_eqi ( c, 'A' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'B' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'D' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'E' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'F' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'G' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'I' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'L' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'O' ) )
    truefalse = TRUE;
  elseif ( ch_eqi ( c, 'Z' ) )
    truefalse = TRUE;
  elseif ( c == '*' )
    truefalse = TRUE;
  else
    truefalse = FALSE;
  end

  return
end


function [a,c] = myhungarian(A)
%MYHUNGARIAN

ndig = 3;

A = round(A*10^ndig);

[a,c] = myhung(A);
c = c *10^(-ndig);


function varargout = histogram(varargin)
% GUI for Plotting historgam and equalizing image arrays
%
% INPUT:
% images - array to plot histograms for (can be a single image as well)
% 'N' - image to display
%
% to run:
%
%   histogram(images,'1')
%
% if want equalized images as output:
%
%   im_eq=threshold(images,'1');
%
%  created by K.Artyushkova
%  January 2004

% Kateryna Artyushkova
% Postdoctoral Scientist
% Department of Chemical and Nuclear Engineering
% The University of New Mexico
% (505) 277-0750
% kartyush@unm.edu

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @histogram_OpeningFcn, ...
                   'gui_OutputFcn',  @histogram_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before histogram is made visible.
function histogram_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to histogram (see VARARGIN)

% Update handles structure
axes(handles.axes1);
cla
data= varargin{1};
n=varargin{2};
n=str2double(n);
iptsetpref('ImshowAxesVisible', 'on')
imagesc(data(:,:,n)), colormap(gray)
set(handles.imi,'string',n);
handles.data=data;
handles.n=n;
guidata(hObject, handles);

% UIWAIT makes histogram wait for user response (see UIRESUME)
% uiwait(handles.figure1);

uiwait(handles.figure1);

% --- Executes during object creation, after setting all properties.
function slice_select_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slice_select (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background, change
%       'usewhitebg' to 0 to use default.  See ISPC and COMPUTER.
usewhitebg = 1;
if usewhitebg
    set(hObject,'BackgroundColor',[.9 .9 .9]);
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

% --- Executes on slider movement.
function slice_select_Callback(hObject, eventdata, handles)
% hObject    handle to slice_select (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider
data=handles.data;
[m,p,q]=size(data);
set(handles.im1,'string',1);
set(handles.imN,'string',q);
step=1/q;
slider_step(1)=step;
slider_step(2)=step;
set(handles.slice_select, 'SliderStep', slider_step, 'Max', q, 'Min',0)
i=get(hObject,'Value');
i=round(i);
    if i==0
        i=1;
    elseif i>=q
        i=q;
    else i=i;
    end
    set(handles.imi,'string',i);
    axes(handles.axes1);
iptsetpref('ImshowAxesVisible', 'on')
imagesc(data(:,:,i)), colormap(gray)
    axes(handles.axes2);
    hist(data(:,:,i))
    handles.n=i;
    guidata(hObject,handles)

% --- Executes on button press in equalize.
function equalize_Callback(hObject, eventdata, handles)
% hObject    handle to equalize (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

data=handles.data;
[m,p,q]=size(data);
for i=1:q
    data_eq(:,:,i)=histeq(uint8(data(:,:,i)));
end
data_eq=double(data_eq);

n=handles.n;
axes(handles.axes1);
iptsetpref('ImshowAxesVisible', 'on')
imagesc(data_eq(:,:,i)), colormap(gray)
      axes(handles.axes2);
    hist(data_eq(:,:,n))
handles.data_eq=data_eq;
    guidata(hObject,handles)

% --- Executes on button press in replace.
function varargout=replace_Callback(hObject, eventdata, handles)
% hObject    handle to replace (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

data=handles.data_eq;
handles.data=data;
handles.output=data;
varargout{1} = handles.output;
guidata(hObject,handles)
uiresume(handles.figure1);

% --- Executes on button press in cancel.
function cancel_Callback(hObject, eventdata, handles)
% hObject    handle to cancel (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
uiresume(handles.figure1);

    % --- Outputs from this function are returned to the command line.
function varargout = histogram_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure

data=handles.data;
handles.output=data;
varargout{1} = handles.output;
close


function RegMeanSquareSimilarity(handles, command, metric)
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

global planC stateS;
indexS = planC{end};

    [originF, spacingF, centerF] = getScanOriginSpacing(planC{indexS.scan}(stateS.imageRegistrationBaseDataset));

    [originM, spacingM, centerM] = getScanOriginSpacing(planC{indexS.scan}(stateS.imageRegistrationMovDataset));

    minstep = str2double(get(handles.para.Similarity_minstep, 'string'));
    maxstep = str2double(get(handles.para.Similarity_maxstep, 'string'));
    iternum = str2double(get(handles.para.Similarity_IterNum, 'string'));

    ScaleFactor = str2double(get(handles.para.Similarity_ScaleFactor, 'string'));
    RotationScale = str2double(get(handles.para.Similarity_RS, 'string'));
    TranslationScale = str2double(get(handles.para.Similarity_TS, 'string'));
    InitialAngle = str2double(get(handles.para.Similarity_InitAngle, 'string'));
    RegLevels = str2double(get(handles.para.Similarity_RegLevels, 'string'));

    output = cell(1, 16);

    FImg = planC{indexS.scan}(stateS.imageRegistrationBaseDataset).scanArray;
    MImg = planC{indexS.scan}(stateS.imageRegistrationMovDataset).scanArray;

    dimF = size(FImg);
    dimM = size(MImg);
    %generate cliped base dataset
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_baseTrans'));
    if ~isempty(clipBox)
        FImg = FImg(clipBox(2):clipBox(4), clipBox(1):clipBox(3), :);
        originF(1) = originF(1) + spacingF(1)*double(clipBox(1)-1);
        originF(2) = originF(2) + spacingF(2)*double(uint16(dimF(1)-clipBox(4)));
    end
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_baseSag'));
    if ~isempty(clipBox)
        FImg = FImg(:, :, clipBox(2):clipBox(4));
        originF(3) = originF(3) + spacingF(3)*double(clipBox(2)-1);
    end

    %generate cliped move dataset
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_movTrans'));
    if ~isempty(clipBox)
        MImg = MImg(clipBox(2):clipBox(4), clipBox(1):clipBox(3), :);
        originM(1) = originM(1) + spacingM(1)*double(clipBox(1)-1);
        originM(2) = originM(2) + spacingM(2)*double(uint16(dimM(1)-clipBox(4)));
    end
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_movSag'));
    if ~isempty(clipBox)
        MImg = MImg(:, :, clipBox(2):clipBox(4));
        originM(3) = originM(3) + spacingM(3)*double(clipBox(2)-1);
    end

%downsample the input datasets
    dsampled = 0;
    if (get(handles.dsampleCheck,'Value') == get(handles.dsampleCheck,'Max'))

        tic;
        xyScale =  2; zScale = 2;
        spacingF = [spacingF(1)*xyScale spacingF(2)*xyScale spacingF(3)*zScale];
        spacingM = [spacingM(1)*xyScale spacingM(2)*xyScale spacingM(3)*zScale];
        disp('downSampling ...');
%         FImg = imdesample3d(FImg,xyScale,zScale);
%         MImg = imdesample3d(MImg,xyScale,zScale);
%         FImg=GPReduce2D(FImg,1);
%         MImg=GPReduce2(MImg,1);
        FImg = FImg(1:xyScale:end, 1:xyScale:end, 1:zScale:end);
        MImg = MImg(1:xyScale:end, 1:xyScale:end, 1:zScale:end);

        toc;
        dsampled = 1;
    end

    switch metric
        case 'mean squares'
            metricIndex = 0;
        case 'normalized correlation'
            metricIndex = 1;
    end

    tic;

%flip the source datasets on X for itk coordinate system
    fdim = 1;
    FImg = flipdim(FImg, fdim);
    MImg = flipdim(MImg, fdim);

% transform initializing modes 0:MomentON 1:GeometryOn 2:initail transform On
    initMode = get(handles.InitTrans, 'value');

%prepare the initial transform matrix
    transMB = planC{indexS.scan}(stateS.imageRegistrationBaseDataset).transM;
    transMM = planC{indexS.scan}(stateS.imageRegistrationMovDataset).transM;
    if isempty(transMM), transMM = eye(4); end;
    if isempty(transMB), transMB = eye(4); end;
    transM = inv(transMB) * transMM;

%flip the moving dataset to match the initial transM
    Tf = eye(4);
    flipM = 0;
    if (get(handles.flipX, 'value'))
        MImg = flipdim(MImg, 2);
        Tf = [-1 0 0 2*centerM(1); 0 1 0 0; 0 0 1 0; 0 0 0 1];
        flipM = 2;
    end
    if (get(handles.flipY, 'value'))
        MImg = flipdim(MImg, 1);
        Tf = [1 0 0 0; 0 -1 0 2*centerM(2); 0 0 1 0; 0 0 0 1];
        flipM = 1;
    end
    if (get(handles.flipZ, 'value'))
        MImg = flipdim(MImg, 3);
        Tf = [1 0 0 0; 0 1 0 0; 0 0 -1 2*centerM(3); 0 0 0 1];
        flipM = 3;
    end
    transM = transM * inv(Tf);
    rotM = transM(1:3, 1:3); transV = transM(1:3, 4);
    rotM = rotM';
    transV = -transV;

%run the registration method
    if strcmpi(command, 'mr')
        try
            [im, Rotation, Offset, TrackData] = MultiRes_Similarity3D(int16(FImg), originF, spacingF, ...
                                                int16(MImg), originM, spacingM, ...
                                                minstep, maxstep, iternum, ...
                                                ScaleFactor, RotationScale, TranslationScale, InitialAngle, ...
                                                RegLevels, metricIndex, rotM, transV, initMode);
        catch
            [im, Rotation, Offset, TrackData] = MultiRes_Similarity3D_64(int16(FImg), originF, spacingF, ...
                                                int16(MImg), originM, spacingM, ...
                                                minstep, maxstep, iternum, ...
                                                ScaleFactor, RotationScale, TranslationScale, InitialAngle, ...
                                                RegLevels, metricIndex, rotM, transV, initMode);
        end
    else
        try
            [im, Rotation, Offset, TrackData] = Similarity3D(int16(FImg), originF, spacingF, ...
                                                int16(MImg), originM, spacingM, ...
                                                minstep, maxstep, iternum, ...
                                                ScaleFactor, RotationScale, TranslationScale, InitialAngle, ...
                                                rotM, transV, initMode);
        catch
            [im, Rotation, Offset, TrackData] = Similarity3D_64(int16(FImg), originF, spacingF, ...
                                                int16(MImg), originM, spacingM, ...
                                                minstep, maxstep, iternum, ...
                                                ScaleFactor, RotationScale, TranslationScale, InitialAngle, ...
                                                rotM, transV, initMode);
        end
    end

    im = flipdim(im, fdim);

    toc;
    RegTime = num2str(ceil(toc/60));

    output{1} = ['Rotation Angle Z = ' num2str(asin(Rotation(1, 2))*45.0/atan(1.0))];
    output{2} = ['Translation X = ' num2str(Offset(1))];
    output{3} = ['Translation Y = ' num2str(Offset(2))];
    output{4} = ['Translation Z = ' num2str(Offset(3))];
    output{5} = ['Number of Iterations = ' num2str(Offset(7))];
    output{6} = ['Best Value = ' num2str(Offset(8))];

    output{7} = ['Rotation Center X = ' num2str(Offset(9))];
    output{8} = ['Rotation Center Y = ' num2str(Offset(10))];
    output{9} = ['Rotation Center Z = ' num2str(Offset(11))];
    output{10} = ['Scale = ' num2str(Offset(12))];
    output{11} = ['Offset X = ' num2str(Offset(13))];
    output{12} = ['Offset Y = ' num2str(Offset(14))];
    output{13} = ['Offset Z = ' num2str(Offset(15))];

    set(handles.OutputList, 'string', output);

%update the transM;
    Tv = [Offset(1) Offset(2) Offset(3)];
    Cv = [Offset(7) Offset(8) Offset(9)];
    Cv(3) = -Cv(3); %CERR z axis is opposite to the ITK.

    rot = reshape(Rotation, 3,3);
    offset = [Offset(13) Offset(14) Offset(15)]';

%     rot(2,1) = -rot(2,1); rot(1,2) = -rot(1,2);
%     rot(1,3) = -rot(1,3); rot(3,1) = -rot(3,1);
%     rot(2,3) = -rot(2,3); rot(3,2) = -rot(3,2);
%
%     offset(1) = -offset(1);
%     offset(2) = -offset(2);
%     offset(3) = -offset(3);

    TM = eye(4);
    TM(:,4) = [offset; 1];

    RM = eye(4);
    RM(1:3, 1:3) = rot;

    newTransform = inv(TM*RM);
    newTransform =  transMB * newTransform * Tf;

    scanSetM = stateS.imageRegistrationMovDataset;
    scanSetF = stateS.imageRegistrationBaseDataset;
    planC{indexS.(stateS.imageRegistrationMovDatasetType)}(scanSetM).transM = newTransform;

% save the resampled dataset
    if (get(handles.saveCheck, 'value'))
        if (~dsampled)
            planC{indexS.scan}(end+1) = planC{indexS.scan}(scanSetF);
            planC{indexS.scan}(end).scanArray = im;
        else
            %imReg = resample(scanSetF, scanSetM); % need to up-sample im ????
            planC{indexS.scan}(end+1) = planC{indexS.scan}(scanSetF);
            planC{indexS.scan}(end).scanArray = imReg;
        end
        controlFrame('refresh');
    end

    sliceCallBack('refresh');

end


% -------------------------------------------------------------------------
function fn = getBatchDagNNWrapper(opts, useGpu)
% -------------------------------------------------------------------------
fn = @(imdb,batch) getBatchDagNN(imdb,batch,opts,useGpu) ;

% -------------------------------------------------------------------------
function inputs = getBatchDagNN(imdb, batch, opts, useGpu)
% -------------------------------------------------------------------------
images = strcat([imdb.imageDir filesep], imdb.images.name(batch)) ;
im = imdb_get_batch_bcnn(images, opts, ...
                            'prefetch', nargout == 0);
labels = imdb.images.label(batch) ;
numAugments = size(im{1},4)/numel(batch);

labels = reshape(repmat(labels, numAugments, 1), 1, size(im{1},4));

if nargout > 0
  if useGpu
    im1 = gpuArray(im{1}) ;
    im2 = gpuArray(im{2}) ;
  else
      im1 = im{1};
      im2 = im{2};
  end
  inputs = {'input', im1, 'netb_input', im2, 'label', labels} ;
end


% Test file for @deltafun/isempty.m

function pass = test_isempty(pref)

if (nargin < 1)
    pref = chebfunpref();
end
%%
d = deltafun();
pass(1) = isempty(d);

f = bndfun([]);
d = deltafun(f);
pass(2) = isempty(d);

d = deltafun(f, []);
pass(3) = isempty(d);

d = deltafun(f, struct('deltaMag', [], 'deltaLoc', []));
pass(4) = isempty(d);

end


function C=multistep(x,N,ld)
x=im2double(x);
[m n]=size(x);
C=x;
for k=0:1:N-1
    R=getcorner(C,m/2^k,n/2^k);
    S=wave_transform(R,ld);
    C=putcorner(C,S);
end
end
function r=getcorner(C,m,n)
    r=C(1:m,1:n);
end
function x=putcorner(c,a)
    [m n]=size(a);
    c(1:m,1:n)=a;
    x=c;
end


classdef tNewInterface < matlab.unittest.TestCase

    properties
        testLoc
        RelTol = 1e-5
        AbsTol = 1e-6
        ToAvoid = [...
            "checkRun", "destinationfile", "estimationinfo", ...
            "BEARpath","datapath","filespath","pref", ...
            "replicationpath","settingspath","sourcefile","settingsm", ...
            "const", "VARtype", "OLS_Bhat", ...
            "IRFt", "IRF", "HD", "Feval", "Fendsmpl", "FEVD", ...
            "F", "CFt", "CF", "ii"]
    end

    methods (TestClassSetup)

        function setup(tc)

            tc.testLoc = fileparts(mfilename('fullpath'));
            % Need to run single threaded to get all the rng defaults
            % correct.
            ps = parallel.Settings;
            if ps.Pool.AutoCreate
                ps.Pool.AutoCreate=false;
                tc.addTeardown(@() set(ps.Pool,'AutoCreate',true))
            end

        end

    end

    methods (TestMethodSetup)

        function prepareTest(tc)
            rng('default');
            s = rng;
            addTeardown(tc, @() rng(s))
        end

    end

    methods (Test, TestTags = {'Git'})

        function tOLSVAR(tc)

            import matlab.unittest.fixtures.TemporaryFolderFixture
            tempFixture = tc.applyFixture(TemporaryFolderFixture);

            resultsFile = "newTest";

            opts= BEARsettings('OLS', 'ExcelFile', fullfile(fullfile(bearroot(),'default_bear_data.xlsx')));
            opts.results_path = tempFixture.Folder;
            opts.results_sub = 'newTest';
            opts.plot = false;

            BEARmain(opts);

            file = exist(fullfile(tempFixture.Folder, resultsFile + ".mat"), 'file');
            tc.verifyEqual(file, 2)
        end

        function tOLSVAR_IRFt2(tc)

            import matlab.unittest.fixtures.TemporaryFolderFixture
            tempFixture = tc.applyFixture(TemporaryFolderFixture);

            resultsFile = "newTest";

            opts= BEARsettings('OLS', 'ExcelFile', fullfile(fullfile(bearroot(),'default_bear_data.xlsx')));
            opts.results_path = tempFixture.Folder;
            opts.results_sub = 'newTest';
            opts.plot = false;
            opts.IRFt = 2;

            BEARmain(opts);

            file = exist(fullfile(tempFixture.Folder, resultsFile + ".mat"), 'file');
            tc.verifyEqual(file, 2)
        end

        function tBVAR_IRFt2(tc)

            import matlab.unittest.fixtures.TemporaryFolderFixture
            tempFixture = tc.applyFixture(TemporaryFolderFixture);

            resultsFile = "newTest";

            opts = BEARsettings('BVAR', 'ExcelFile', fullfile(fullfile(bearroot(),'default_bear_data.xlsx')), ...
                'prior', 'minnesota_univariate', 'IRFt', 4);
            opts.prior=11;
            opts.IRFt=2;
            opts.results_path = tempFixture.Folder;
            opts.results_sub = 'newTest';
            opts.plot = false;
            BEARmain(opts);

            file = exist(fullfile(tempFixture.Folder, resultsFile + ".mat"), 'file');
            tc.verifyEqual(file, 2)
        end

    end

end