16 May 2004 immoments added
            ploto     added
            featsel routines with crossval implemented
25 Jun 2004 fdsc      added
30 Aug 2004 proxm     homogeneous measure added (x*y)^p
            disperror, confmat: writing to files enabled
26 Sep 2004 gaussm, emclust: get right number of components
            crisp / soft label handling for these routines
30 Sep 2004 plotr     allow multiple error curves
            scalem    variance option corrected
21 Oct 2004 svc_nu, svo_nu, added
 6 Dec 2004 parzendc, parzen_map: soft labels
            nmc: bug fix, allow soft labels
            prtest: bug fix, label generation
12 Dec 2004 plotr: cell array of error structures
14 Dec 2004 setlabels, roc, normm: bug fixes to correct / prevent
            reordering of lablist
20 Jan 2005 prwarning level now default 1
            some warning levels adapted
            in particular for empty priors
 1 Feb 2005 clevalf, debugged from reusing the same testset
24 Apr 2005 labcmp added
29 Oct 2005 trying to avoid prior warnings

----------------------------

 8 Mar 2006 start datafile options
26 Sep 2006 multiple labeling, see multi-labeling
26 Sep 2006 structure field handling for user and ident field in datasets
28 Nov 2006 testauc added

18 Dec 2006 global variables like PRMEMORY, PRTRACE, GRIDSIZE, etc
            are made persistent instead of global
19 Dec 2006 plotr renamed in plote (make space for a regression plot command)
            svc svc_nu: general option for kernel computation
22 Mar 2007 datafile construct ready
19 Apr 2007 Normal_map: inversion at learning
            Gaussm, mogs, improved: noise, more trials, regularisation
17 May 2007 NAIVEBC generalised with PARZENM and GAUSSM
18 May 2007 Streamlining PRPROGRESS and CLOSEMESS
            NMC now based on normal distributions with identically shaped
            spherical classifiers. This gives a better soft output. Consequently
            the soft version of EMCLUST is improved as it uses NMC for
            initialisation.
 5 Jun 2007 TESTC extended with various criteria
            Automatic parameter optimization in some routines
            RSSCC and RBSVC added
 3 Jul 2008 PRPROGRESS partially replaced by PRWAITBAR
10 Jul 2008 ident reorganised
21 Jul 2008 createdatafile
18 Aug 2008 Image Database Retrieval GUI
 5 Jan 2009 im_patch, band2obj and bandsel added
- new trainable combiners: naivebcc and mlrc (thanks to Chunxia!)
- Leave One Set Out crossvalidation: loso
- testc accepts missing classes in case of no_priors
- implementation of multi-band time-signals as multiband 1-D images
- this script generates now proper p-code :-)
10 Mar 2009 DCSC added
18 Mar 2009 MODSELC added

April  2011 FDSC, MDSC, DISNORM added


%kcpRGBNTSCtoUVWstar 'converts an image from RGB NTSC to U*V*W* '
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros cpRGBNTSCtoUVWstar.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'First Input data object'
% OutputFile: o 'Output', required: 'Resulting output data object'
%
% Example: o = kcpRGBNTSCtoUVWstar(i, {'i','';'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% cpRGBNTSCtoUVWstar - converts an image from RGB NTSC to U*V*W*
%
%  DESCRIPTION
% call ckfromRGBNTSC with the parameter -labstar to convert an image from RGB NTSC to U*V*W*
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
% All references for the COLOR toolbox are on the file $COLOR/Readme.html
%
%  COPYRIGHT
% Copyright (C) 1997 Rafael Santos. Khoros (C) Khoral Research, Inc.
%

function varargout = kcpRGBNTSCtoUVWstar(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kcpRGBNTSCtoUVWstar(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'o', '__output'};
maxval={0,0};
minval={0,0};
istoggle=[0,0];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'ckfromRGBNTSC"  -uvwstar'],Inputs,narglist);


function result = matc(sf,tf)
% Compare two mat files
% matc matfile1.mat matfile2.mat

% Copyright 2004, Dr. Xianyao Chen, xianyaochen@yahoo.com.cn
% Last Modified by Xianyao Chen, 08-June-2004

if (nargin ~= 2)
  return
end
if exist(sf) ~=2
    msg = sprintf('%s%s','Not valid mat file: ',sf);
%     fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
   fprintf('%s',msg)
    return
end
if exist(tf) ~=2
    msg = sprintf('%s%s','Not valid mat file: ',tf);
%     fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
   fprintf('%s',msg)
    return
end
save #~tmp1.mat -mat
clear
load #~tmp1 sf

load(sf)
clear sf

ws = whos;
save #~tmp2.mat -mat
clear

load #~tmp1
load #~tmp2
delete('#~tmp2.mat');

m1 = size(ws,1);

warning off
% nPos = 0;
for k = 1:m1
    var = ws(k).name;
    as = load(sf,var);
    at = load(tf,var);
    atn = fieldnames(at);
    if k == 1
        msg = sprintf('%s%s','Source File: ',sf,' --- Target File: ',tf');
        fprintf('%s\n',msg)
        msg = sprintf('%50s','--------------------------------------------------');
        fprintf('%s\n',msg)
%         msg = sprintf('%s','----------------------------------------------------------------------------------------------------------------------------');
%         fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
%         fprintf('\n')
    end

    if isempty(atn)
        msg = sprintf('%12s%12s%6s%s','Variable :: ',var,'  ||  ',' not exist');
        fprintf('%s\n',msg)
%         msg = sprintf('%12s%12s%20s%20s%20s%20s%s','Variable :: ',var,'    |  Source File: ',sf,' ---  Target File: ',tf,' :: not exist');
%         fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
%         fprintf('\n')
        continue
    end
    aas = struct2cell(as);
    aat = struct2cell(at);
    if ~isequal(aas{1},aat{1})
        msg = sprintf('%12s%12s%6s%s','Variable :: ',var,'  ||  ',' not equal');
        fprintf('%s\n',msg)
%         msg = sprintf('%12s%12s%20s%20s%20s%20s%s','Variable :: ',var,'    |  Source File: ',sf,' ---  Target File: ',tf,' :: not equal');
%         fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
%         fprintf('\n')
        continue
    else
        msg = sprintf('%12s%12s%6s%s','Variable :: ',var,'  ||  ',' equal');
        fprintf('%s\n',msg)
%         msg = sprintf('%12s%12s%20s%20s%20s%20s%s','Variable :: ',var,'    |  Source File: ',sf,' ---  Target File: ',tf,' :: Exactly Equal');
%         fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
%         fprintf('\n')
        continue
    end
end
msg = sprintf('%50s','--------------------------------------------------');
fprintf('%s\n\n',msg)

% msg = sprintf('%s','----------------------------------------------------------------------------------------------------------------------------');
% fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
% fprintf('\n')

clear
load #~tmp1 tf

load(tf)
clear tf

ws = whos;
save #~tmp2.mat -mat
clear

load #~tmp1
load #~tmp2
delete('#~tmp2.mat');

m1 = size(ws,1);
warning off

for k = 1:m1
    var = ws(k).name;
    as = load(tf,var);
    at = load(sf,var);
    atn = fieldnames(at);
    if k == 1
        msg = sprintf('%s%s','Source File: ',tf,' --- Target File: ',sf');
        fprintf('%s\n',msg)
        msg = sprintf('%50s','--------------------------------------------------');
        fprintf('%s\n',msg)
        %fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
        %fprintf('\n')
    end

    if isempty(atn)
        msg = sprintf('%12s%12s%6s%s','Variable :: ',var,'  ||  ',' not exist');
        fprintf('%s\n',msg)
%         fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
%         fprintf('\n')
        continue
    end
    aas = struct2cell(as);
    aat = struct2cell(at);
    if ~isequal(aas{1},aat{1})
        msg = sprintf('%12s%12s%6s%s','Variable :: ',var,'  ||  ',' not equal');
        fprintf('%s\n',msg)
%         msg = sprintf('%12s%12s%20s%20s%20s%20s%s','Variable :: ',var,'    |  Source File: ',tf,' ---  Target File: ',sf,' :: not equal');
%         fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
%         fprintf('\n')
        continue
    else
        msg = sprintf('%12s%12s%6s%s','Variable :: ',var,'  ||  ',' equal');
        fprintf('%s\n',msg)
%         msg = sprintf('%12s%12s%20s%20s%20s%20s%s','Variable :: ',var,'    |  Source File: ',tf,' ---  Target File: ',sf,' :: Exactly Equal');
%         fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
%         fprintf('\n')
        continue
    end
end
warning on

msg = sprintf('%50s','--------------------------------------------------');
fprintf('%s\n',msg)
% fprintf( [ repmat( '\b', 1, nPos ), '%s' ], msg),
% fprintf('\n')

delete('#~tmp1.mat')


classdef Postprocess < handle

    properties (Access = protected)
        outFileName
        resultsDir

        resultPrinter
        meshPrinter

        mshDataBase
        resDataBase
    end

     methods (Access = public)

        function obj = Postprocess(postCase,d)
            obj.init(d);
            obj.createOutputDirectory();
            obj.createMeshPrinter();
            obj.createResultPrinter(postCase);
        end

        function print(obj,iter,d)
            obj.printMeshFile(iter);
            obj.printResFile(iter,d)
        end

        function r = getResFile(obj)
            r = obj.outFileName;
        end

    end

    methods (Access = private)

        function init(obj,d)
            obj.outFileName = d.outFileName;
            obj.createResultsDirName();
            obj.computeDataBaseForMeshFile(d);
            obj.computeDataBaseForResFile(d);
        end

        function createMeshPrinter(obj)
            obj.meshPrinter = MeshPrinter();
        end

        function createResultPrinter(obj,postCase)
            obj.resultPrinter  = ResultsPrinter.create(postCase,obj.resDataBase);
        end

        function printResFile(obj,iter,d)
            obj.resultPrinter.print(iter,d);
        end

       	function printMeshFile(obj,iter)
            d = obj.mshDataBase;
            d.iter = iter;
            obj.meshPrinter.print(d);
        end

        function createOutputDirectory(obj)
            dir = obj.resultsDir;
            if ~exist(dir,'dir')
                mkdir(dir)
            end
        end

        function computeDataBaseForResFile(obj,dI)
            obj.resDataBase = dI;
            obj.resDataBase.resultsDir = obj.resultsDir;
        end

        function computeDataBaseForMeshFile(obj,dI)
            d.coordinates    = dI.coordinates;
            d.connectivities = dI.connectivities;
            d.outFileName    = dI.outFileName;
            d.npnod          = dI.npnod;
            d.pdim           = dI.pdim;
            d.nnode          = dI.nnode;
            d.nelem          = dI.nelem;
            d.ndim           = dI.ndim;
            d.etype          = dI.etype;
            d.resultsDir     = obj.resultsDir;
            obj.mshDataBase = d;
        end

        function createResultsDirName(obj)
           path = pwd;
           obj.resultsDir = fullfile(path,'Output',obj.outFileName);
        end

     end

end


function data = set_infer_chanlocs(data,disambiguation_rule)
% Infer the chanlocs subfields (positions and type) from labels.
% Data = set_infer_chanlocs(Data,DisambiguationRule)
%
% In:
%   Data   : some EEGLAB data set with a chanlocs field or the chanlocs field itself
%
%   DisambiguationRule : rule to apply to disambiguate montages when a given set of channel labels
%                        match multiple montage files similarly well. Can be:
%                        * 'coverage' : picks the one with maximum coverage
%                        * 'first' : picks the first one in the list of candidates (out of those that
%                                    have reasonable coverage)
%                        * 'deduce' : uses correlation analysis to deduce the best fit (can be slow)
%                        * filename : uses the montage with the given file name
%                        (default: 'deduce')
%
% Out:
%   Data   : original set with updated chanlocs field, or the updated chanlocs themselves
%
% Notes:
%   Parameters cannot be passed by name to this function.
%   To add a custom cap design to set_infer_chanlocs, see documentation in the
%   bcilab:/resources/caps folder.
%
%
% Examples:
%   % given a data set with labeled channels (but no locations), fill in standard channel locations
%   eeg = set_infer_chanlocs(eeg)
%
%   % given a .chanlocs field of a data set with only labels, fill in standard channel locations
%   chanlocs = set_infer_chanlocs(eeg.chanlocs)
%
%   % given a cell array of channel labels, obtain a chanlocs structure with locations filled in
%   chanlocs = set_infer_chanlocs({'C3','Cz','C4'})
%
%   % given a chanlocs file in a format recognized by EEGLAB, obtain a corresponding chanlocs struct
%   chanlocs = set_infer_chanlocs('mylocs.sfp')
%
% See also:
%   io_loadset
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2010-11-05

% path where *.cap files are located
cappath = 'resources:/caps/';

if nargin < 2
    disambiguation_rule = 'deduce'; end

% obtain the chanlocs
signal = [];
if isfield(data,{'head','parts'})
    data = exp_eval(data); end
if isfield(data,'chanlocs')
    locs = data.chanlocs;
    signal = data;
    if ~isfield(data.chaninfo,'labelscheme')
        data.chaninfo.labelscheme = '10-20'; end
else
    locs = data;
end

% channel labels given as a cell array
if iscellstr(locs)
    locs = struct('labels',locs); end;
if ischar(locs)
    locs = readlocs(env_translatepath(locs)); end
if ~isstruct(locs)
    error('The given data is not in an appropriate format (expected either a file name, a cell array of labels, a .chanlocs struct, or an EEGLAB dataset struct).'); end

% --- find best-matching cap if some locs missing ---

if (~all(isfield(locs,{'X','Y','Z'})) || all(cellfun('isempty',{locs.X}))) && ~isempty(locs)
    % get a list of all cap files
    capfiles = dir(env_translatepath(cappath));
    capfiles = capfiles(cellfun(@(n)~isempty(strfind(n,'.cap')),{capfiles.name}));
    caps = cellfun(@(n){[cappath n]},{capfiles.name});

    % for each cap file, try to match channel labels
    for c = 1:length(caps)
        try
            cap = caps{c};
            capdata{c} = hlp_microcache('chanlocs',@io_load,cap,'-mat');
            locdb = capdata{c}.CAP;
            fitlocs{c} = locs;
            switch capdata{c}.MATCH
                case {'exact','nocase_exact'}
                    % exact matching (both cases supported)
                    if ~isempty(strfind(capdata{c}.MATCH,'nocase'))
                        [found,idx_in_locdb,idx_in_res] = intersect(lower({locdb.labels}),lower({locs.labels})); %#ok<ASGLU>
                    else
                        [found,idx_in_locdb,idx_in_res] = intersect({locdb.labels},{locs.labels}); %#ok<ASGLU>
                    end
                    for fname = fieldnames(locdb)'
                        [fitlocs{c}(idx_in_res).(fname{1})] = locdb(idx_in_locdb).(fname{1}); end
                    [fitlocs{c}(idx_in_res).type] = deal('EEG');
                case {'substr','nocase_substr'}
                    % sub-string matching (both cases supported)
                    [found,idx_in_res,idx_in_locdb] = hlp_microcache('chanlocs',@do_matching,fitlocs{c},locdb,~isempty(strfind(capdata{c}.MATCH,'nocase'))); %#ok<ASGLU>
                    for fname = fieldnames(locdb)'
                        [fitlocs{c}(idx_in_res).(fname{1})] = locdb(idx_in_locdb).(fname{1}); end %#ok<*AGROW>
                    [fitlocs{c}(idx_in_res).type] = deal('EEG');
            end
            fraction_found(c) = 1-mean(cellfun('isempty',{fitlocs{c}.X}));
        catch e
            fprintf('Not matching channel labels with cap %s due to error: %s',cap,hlp_handleerror(e));
            fraction_found(c) = 0;
        end
    end

    % determine whether we have a clear-cut case
    [sorted_fractions,order] = sort(fraction_found,'descend');
    if max(sorted_fractions) < 0.5
        fprintf('WARNING: only %.0f%% of your channel labels match any known cap design; inferred locations might be wrong. Please consider adding your cap to set_infer_chanlocs.',100*max(sorted_fractions)); end
    if sorted_fractions(1) >= 1.5*sorted_fractions(2)
        % at least twice as many channels matched for this cap as for the next best one: keep it
        bestidx = order(1);
    elseif ~isempty(signal) && size(signal.data,1)==length(locs)
        % not a clear-cut case but we have a signal to work with
        switch disambiguation_rule
            case 'coverage'
                fprintf('Multiple known cap designs match to your data''s channel labels; picking the one with greatest coverage...\n');
                bestidx = order(1);
            case 'first'
                fprintf('Multiple known cap designs match to your data''s channel labels; picking the first one in the list...\n');
                bestidx = 1;
            case 'deduce'
                fprintf('Multiple known cap designs match to your data''s channel labels; determining the best fit...\n');
                quality = hlp_diskcache('montage_quality',@fit_quality,signal,sorted_fractions,order,fitlocs);
                % assess quality of best fit
                if max(quality)<0.3
                    fprintf('WARNING: Did not find a cap design that matches your data. You need to add channel locations for your cap to set_infer_chanlocs to use any function that requires these locations.\n');
                    bestidx = NaN;
                else
                    if max(quality)<0.5
                        fprintf('WARNING: The agreement between your data and the available cap designs is low and the chosen locations might be partially wrong. Either your data is too noisy for a reliable determination or your cap design differs from the known ones.\n');  end
                    bestidx = order(argmax(quality));
                end
            otherwise
                % assume that a montage file name was given
                match = ~cellfun('isempty',strfind(caps,disambiguation_rule));
                if nnz(match) == 1
                    bestidx = find(match);
                elseif nnz(match) > 1
                    fprintf('WARNING: multiple montages match your montage name: picking the first one.\n');
                    bestidx = find(match,1);
                else
                    % assume that this is a file name and try to load it
                    bestidx = NaN;
                    tmp = getfield(hlp_microcache('chanlocs',@io_load,disambiguation_rule,'-mat'),'CAP');
                    if ~isequal({tmp.labels},{locs.labels})
                        error('Currently the given cap file must match the available channel labels exactly.'); end
                end
        end
    elseif sorted_fractions(1)>sorted_fractions(2)
        % not a clear-cut case but minor evidence in favor of best cap
        fprintf('NOTE: multiple cap designs are compatible with your channel labels, using the best-matching one; inferred locations might be wrong.\n');
        bestidx = order(1);
    else
        % no clear winner
        fprintf('WARNING: multiple cap designs match your channel labels equally well, using the first cap in the list; inferred locations may be wrong.\n');
        bestidx = order(1);
    end

    % use the picked locations
    if ~isnan(bestidx)
        fprintf('  using montage %s.\n',caps{bestidx});
        locs = fitlocs{bestidx};
        if isstruct(data) && isfield(data,'data')
            data.chaninfo.labelscheme = capdata{bestidx}.SCHEME;
            data.chaninfo.nosedir = capdata{bestidx}.NOSE;
        end
    end

    % optionally optimize the head center
    if isfield(capdata{bestidx},'RECENTER') && capdata{bestidx}.RECENTER
        try
            if  mean(cellfun('isempty',{locs.X})) < 0.75
                locs = hlp_microcache('chanlocs',@pop_chanedit,locs,'eval','chans = pop_chancenter( chans, [],[]);'); end
        catch e
            fprintf('Failed trying to optimized the head center location for your cap montage due to error: %s\n',e.message);
        end
    end
end

% --- do post-processing ---

if ~isfield(locs,'labels')
    for k=data.nbchan:-1:1
        locs(k).labels = num2str(k); end
end
if ~isfield(locs,'type')
    locs(1).type = []; end
if ~isfield(locs,'theta')
    locs(1).theta = []; end

% reset 'unknown' channel types to empty
for k=1:length(locs)
    if strcmpi(locs(k).type,'unknown')
        locs(k).type = ''; end
end

% if some channel types are missing, try to look them up
empty_type = cellfun('isempty',{locs.type});
if any(empty_type)
    % assign all successfully retrieved EEG channels
    [locs(~cellfun('isempty',{locs.theta}) & empty_type).type] = deal('EEG');

    % assign the most common prefixes
    prefixes = {'eo','EOG','em','EMG','ec','ECG','ex','EXG','gsr','GSR'};
    for p=1:2:length(prefixes)
        [locs(strncmpi(prefixes{p},{locs.labels},length(prefixes{p})) & empty_type).type] = deal(prefixes{p+1}); end

    % also look for occurrence of EO, EM, ECG, EX, and GSR patterns
    patterns = {'EO','EOG','EM','EMG','ECG','ECG','EX','EXG','GSR','GSR','RE','EOG','LE','EOG'};
    for p=1:2:length(patterns)
       [locs(~cellfun('isempty',strfind({locs.labels},patterns{p})) & empty_type).type] = deal(patterns{p+1}); end

   % assign type 'EEG' to all numerically labeled channels (default assumption)
    [locs(cellfun(@(x)~isempty(str2num(x)),{locs.labels})).type] = deal('EEG'); %#ok<ST2NM>

    % assign 'EEG' to all unknown channels that are preceded and followed by EEG channels...
    filled_in = false;
    for k = find(cellfun('isempty',{locs.type}))
        % check if there is an EEG channel before this one (besides other unknowns)
        eeg_before = false;
        for j=k-1:-1:1
            if ~isempty(locs(j).type)
                if strcmp(locs(j).type,'EEG')
                    eeg_before = true; end
                break;
            end
        end
        % check if there is an EEG channel after this one (besides other unknowns)
        eeg_after = false;
        for j=k+1:length(locs)
            if ~isempty(locs(j).type)
                if strcmp(locs(j).type,'EEG')
                    eeg_after = true; end
                break;
            end
        end
        if eeg_before && eeg_after
            locs(k).type = 'EEG';
            filled_in = true;
        end
    end
    if filled_in
        disp('Note: some channels could not clearly be recognized as EEG (not in the 10-5 system), but were preceded and followed by EEG channels; assuming they are EEG.'); end

    % assign 'unknown' to the rest
    [locs(cellfun('isempty',{locs.type})).type] = deal('unknown');
end

if isfield(data,'chanlocs')
    data.chanlocs = locs;
else
    data = locs;
end

% function for sub-string matching between labels and a location struct array
function [found,idx_in_res,idx_in_locdb] = do_matching(fitlocs,locdb,use_lower)
found = {};
idx_in_res = [];
idx_in_locdb = [];
fitlabels = {fitlocs.labels};
dblabels = {locdb.labels};
if use_lower
    fitlabels = lower(fitlabels);
    dblabels = lower(dblabels);
end
for k=1:length(locdb)
    match = ~cellfun('isempty',strfind(fitlabels,dblabels{k}));
    if any(match)
        found{end+1} = locdb(k).labels;
        idx_in_res(end+1) = find(match,1);
        idx_in_locdb(end+1) = k;
    end
end

function quality = fit_quality(signal,sorted_fractions,order,fitlocs)
% first calculate bandpass-filtered signal X
attenuation = 80;
frequencies = min(1,2*[0.5 2 45 50]/signal.srate);
w = design_kaiser(frequencies(1),frequencies(2),attenuation,true);
B = design_fir(length(w)-1,[0 frequencies 1],[0 0 1 1 0 0],[],w);
try
    % try to process all data at once
    X = filtfilt_fast(B,1,signal.data')';
catch
    % fall back to channel-by-channel processing (if out of memory)
    for c=signal.nbchan:-1:1
        X(c,:) = filtfilt_fast(B,1,signal.data(c,:)')'; end
end

% for each cap design that matches reasonably well...
for k=1:nnz(sorted_fractions(1) < 2*sorted_fractions)
    o = order(k);
    % get matched locations
    tmp = fitlocs{o};
    [x,y,z] = deal({tmp.X},{tmp.Y},{tmp.Z});
    usable_channels = find(~cellfun('isempty',x) & ~cellfun('isempty',y) & ~cellfun('isempty',z));
    positions = [cell2mat(x(usable_channels));cell2mat(y(usable_channels));cell2mat(z(usable_channels))];
    % calculate channel interpolation matrix
    M = hlp_diskcache('montages',@interpolation_matrix,positions);
    % calculated interpolated signal Y
    Y = M*X(usable_channels,:);
    % calculated median of windowed correlation between X and Y
    window_len = 1*signal.srate;
    wnd = 0:window_len-1;
    offsets = round(1:window_len:size(Y,2)-window_len);
    W = length(offsets);
    corrs = [];
    for o=W:-1:1
        XX = X(usable_channels,offsets(o)+wnd)'; XX = bsxfun(@minus,XX,mean(XX));
        YY = Y(:,offsets(o)+wnd)'; YY = bsxfun(@minus,YY,mean(YY));
        corrs(:,o) = sum(XX.*YY)./(sqrt(sum(XX.^2)).*sqrt(sum(YY.^2)));
    end
    chancorr = median(corrs,2);
    % use average self-correlation across channels as quality index for this cap design
    quality(k) = mean(chancorr);
end

function M = interpolation_matrix(positions)
% interpolation_matrix_version<1.0> -- for the cache
fprintf('  calculating interpolation matrix for your montage; this is a one-time process');
range = 1:length(positions);
M = zeros(length(positions));
for k=range
    M(k,range~=k) = real(sphericalSplineInterpolate(positions(:,range~=k),positions(:,k)))';
    fprintf('.');
end
fprintf('\n');


function planC = updateStructureMatrices(planC, editStructNum, sliceNumsV)
%"updateStructureMatrices"
%    Updates uniformized data for changes in structure contours.  editStructNum
%    is the number of the structure that has changed.  sliceNumsV is an optional
%    parameter specifying which uniformized slices should be updated.  If
%    it is not included, all relevant slices are re-uniformized.
%
%WARNING: sliceNumsV input parameter is in UNIFORMIZED slices.
%WARNING: Uniformization is performed using raster segments.  Raster
%         segments must be re-generated first!
%
% Created by   : V H Clark, 22 Aug 02.
% Last Modified: JOD, 14 Oct 02.
%              : JRA, 3 Oct 03.
%              : JRA, 10 Nov 04.
%
%Usage:
%   planC = updateStructureMatrices(planC, editStructNum, sliceNumsV)

	indexS = planC{end};

    %Figure out what relative structNum this is for the specified scanNum;
    [scanNum, relStructNum] = getStructureAssociatedScan(editStructNum, planC);

	%Get background data on scan, uniformized data assoc. with structure.
	scanInfo            = planC{indexS.scan}(scanNum).scanInfo;
	sizeArray           = getUniformScanSize(planC{indexS.scan}(scanNum));
    [xV, yV, zV]        = getUniformScanXYZVals(planC{indexS.scan}(scanNum));
    [xVs, yVs, zVs]     = getScanXYZVals(planC{indexS.scan}(scanNum));
	CTOriginalZValues   = [scanInfo(:).zValue];
	CTSliceThickness    = [scanInfo(:).sliceThickness];
	CTdeltaX            = abs(xV(2) - xV(1));
	CTdeltaY            = abs(yV(2) - yV(1));

	%Retrieve the structure's raster segments.
	[allSegmentsM, planC, isError] = getRasterSegments(editStructNum, planC);

    reusableZerosM = repmat(logical(0),[sizeArray(1), sizeArray(2)]);

    %Initialize structureArray and bits array if they dont exist.
    if length(planC{indexS.structureArray}) < scanNum;
        tmp = uint16([0 0 0]);
        tmp(1,:) = [];
        planC{indexS.structureArray}(scanNum).indicesArray = tmp;
        tmp = uint8(0);
        tmp(1) = [];
        planC{indexS.structureArray}(scanNum).bitsArray = tmp;
    end

	%If we have exceeded the max for current datatype, increase it.
	switch class(planC{indexS.structureArray}(scanNum).bitsArray)
        case 'uint8'
            if relStructNum > 8
                planC{indexS.structureArray}(scanNum).bitsArray = uint16(planC{indexS.structureArray}(scanNum).bitsArray);
            end
        case 'uint16'
            if relStructNum > 16
                planC{indexS.structureArray}(scanNum).bitsArray = uint32(planC{indexS.structureArray}(scanNum).bitsArray);
            end
        case 'uint32'
            if relStructNum > 32
                planC{indexS.structureArray}(scanNum).bitsArray = double(planC{indexS.structureArray}(scanNum).bitsArray);
            end
        case 'double'
            %Can up to uint64 here if 52 is not enough in the future.
	end

    %Clear old data for this structure.  If sliceNumsV is specified clear
    %only those slices, otherwise clear all slices.
    if exist('sliceNumsV')
        if MLVersion < 6.5
            %ML6.1 ismember cannot handle uint16.  Must double in this case.
            tf = ismember(double(planC{indexS.structureArray}(scanNum).indicesArray(:,3)), sliceNumsV);
        else
            tf = ismember(planC{indexS.structureArray}(scanNum).indicesArray(:,3), sliceNumsV);
        end
        planC{indexS.structureArray}(scanNum).bitsArray(tf) = bitset(planC{indexS.structureArray}(scanNum).bitsArray(tf), relStructNum, 0);
    else
        planC{indexS.structureArray}(scanNum).bitsArray = bitset(planC{indexS.structureArray}(scanNum).bitsArray, relStructNum, 0);
    end

	%Now we need to generate the indicesM entries for the modified structure
	k = 0;
	if ~isempty(allSegmentsM)
      wb = waitbar(0, ['Saving updated data for ' planC{indexS.structures}(editStructNum).structureName '...']);

      %If no predefined slice numbers were passed in...
      if ~exist('sliceNumsV')
          %Only use slice numbers bookending the raster segments' Zs
          minRasterZ = min(allSegmentsM(:,1));
          maxRasterZ = max(allSegmentsM(:,1));

          %Add a one slice buffer to cover all relevant uni. slices.
          minRasterZ = zVs(max(max(find(zVs <= minRasterZ)) - 1, 1));
          maxRasterZ = zVs(min(min(find(zVs >= maxRasterZ)) + 1, length(zVs)));

          %1 and length(zV) are included to prevent boundary errors.
          minUniSlice = max([find(zV < minRasterZ) 1]);
          maxUniSlice = min([find(zV > maxRasterZ) length(zV)]);

          sliceNumsV = minUniSlice:maxUniSlice;
      end

      %Preallocate the mask array.
      structM = repmat(reusableZerosM, [1 1 length(sliceNumsV)]);

      %Build the mask array, then add the mask to the uniform data.
      for zSliceUniformValue = zV(sliceNumsV)
        k = k+1;
        waitbar(k/length(sliceNumsV), wb);
        structSlc = findStructureMatrixForOneZSlice(allSegmentsM, zSliceUniformValue, CTOriginalZValues, CTSliceThickness, CTdeltaX, CTdeltaY, reusableZerosM);
        structM(:,:,k) = logical(structSlc);
      end
      planC = uniformAdd(structM, scanNum, sliceNumsV, relStructNum, planC);
	end

	if exist('wb')
      close(wb);
	end
	return

function planC = uniformAdd(mask3M, scanNum, sliceNumV, structNum, planC)
%"uniformAdd"
%   Add a single structure's slice(s) to the Uniformized Data for
%   structNum.

	indexS = planC{end};

	siz = getUniformScanSize(planC{indexS.scan}(scanNum));

	indicesM = planC{indexS.structureArray}(scanNum).indicesArray;
	bitsM    = planC{indexS.structureArray}(scanNum).bitsArray;

	%Get indices on this slice.

    if MLVersion < 6.5
        %ismember cannot handle uint16s in ML6.1.
    	ind = find(ismember(double(indicesM(:,3)), sliceNumV));
    else
        ind = find(ismember(indicesM(:,3), sliceNumV));
    end

	[r,c,s] = find3d(mask3M);
	s = sliceNumV(s);
	myDataPoints = [r',c',s'];

	%Convert from rcs to index, makes intersect and setdiff faster.
    %Do this manually since sub2ind has major overhead.
    multiM = cumprod(siz);
    mDP = double(r) + (double(c)-1)*multiM(1) + (double(s)-1)*multiM(2);
	iM  = double(indicesM(ind,1)) + (double(indicesM(ind,2))-1)*multiM(1) + (double(indicesM(ind,3))-1)*multiM(2);

	%Find voxels in both sets.
	[c, ia, ib] = intersect(mDP, iM);

	%Find points not already in Uniformized data.
	bitsM(ind) = bitset(bitsM(ind), structNum, 0);
	bitsM(ind(ib)) = bitset(bitsM(ind(ib)), structNum, 1);
	[c, i] = setdiff(mDP, c);

	newValueIndicies = i;
	numNewIndicies = length(i);

	%Add these new points.
	indicesM = [indicesM;myDataPoints(newValueIndicies, :)];

	a = 0;
	%set the bits of the new points--since they are new only this struct must
	%be flipped.
	a = bitset(a, structNum, 1);
	bitsM(length(bitsM)+1:length(indicesM)) = a;

	planC{indexS.structureArray}(scanNum).indicesArray = indicesM;
	planC{indexS.structureArray}(scanNum).bitsArray = bitsM;


function VDSR(datasetName, SF, model, outRoute)

if isempty(model)
    error('no model');
else
    modelPath = ['VDSR model/',model];
    %gpu = 1;
    gpu = 0; % MAGI-ADAPT
end

model = load(modelPath);
net = model.net;
net = vl_simplenn_tidy(net);

managableMax = 300000;

dataDir = fullfile('data', datasetName);
f_lst = dir(fullfile(dataDir, '*.*'));
evaltable = zeros(numel(f_lst),2);
for f_iter = 1:numel(f_lst)
    f_info = f_lst(f_iter);
    if f_info.isdir, continue; end
    [~,imgName,~] = fileparts(f_lst(f_iter).name);
    imGT = imread(fullfile(dataDir, f_info.name));
    if size(imGT,3) > 1
        im = rgb2ycbcr(imGT);
    else
        im = imGT;
    end
    imhigh = modcrop(im, SF);
    imhigh = single(imhigh)/255;
    imlow = imresize(imhigh, 1/SF, 'bicubic');
    imlow = imresize(imlow, SF, 'bicubic');
    if size(imlow,3)>1
        imlowy = imlow(:,:,1);
        imlowy = max(16.0/255, min(235.0/255, imlowy));
        imlowcb = imlow(:,:,2);
        imlowcr = imlow(:,:,3);
    else
        imlowy = imlow;
    end

    if size(imlowy,1)*size(imlowy,2) > managableMax
        impred = runPatchVDSR(net, imlowy, gpu, 20);
    else
        if gpu, imlowy = gpuArray(imlowy); end;
        impred = runVDSR(net, imlowy, gpu);
    end
    if size(imGT,3) > 1
        impredColor = cat(3,impred,imlowcb,imlowcr);
        imwrite(ycbcr2rgb(uint8(impredColor*255)), fullfile(outRoute, [imgName, '.png']));
    else
        impredColor = impred;
        imwrite(uint8(impredColor*255), fullfile(outRoute, [imgName, '.png']));
    end
    imtest = imread(fullfile(outRoute, [imgName, '.png']));
    [psnr, ssim] = compute_diff(imGT,imtest,SF);
    evaltable(f_iter,1) = psnr; evaltable(f_iter,2) = ssim;
end

save(fullfile(outRoute,'psnr_ssim.mat'),'evaltable');


function addCERRtoPath(pathStr)
% function addCERRtoPath(pathStr)
%
% This function adds sub-directories from CERR distribution to Matlab/Octave path
% pathStr is the absolute path of CERR.
%
% APA, 7/30/2020

pathC = genpath(pathStr);
pathC = strsplit(pathC,';');
indGitV = cellfun(@isempty,strfind(pathC,{'.git'}));
pathC = pathC(indGitV);
addpath(strjoin(pathC,';'))


function varargout = panel_bem(varargin)
% PANEL_BEM: Options for the construction of BEM layers (GUI).
%
% USAGE:  bstPanelNew = panel_bem('CreatePanel')
%                   s = panel_bem('GetPanelContents')

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2011

eval(macro_method);
end

%% ===== CREATE PANEL =====
function [bstPanelNew, panelName] = CreatePanel()  %#ok<DEFNU>
    panelName = 'BemOptions';
    % Java initializations
    import java.awt.*;
    import javax.swing.*;
    % Create main main panel
    jPanelNew = gui_river();
    % Default OpenMeeg options
    BemOptions.nvert = [1922, 1922, 1922];
    BemOptions.thickness = [7 4 3];  % outer-skin, inner-outer, brain-inner
    VertList = {'162', '273', '362', '482', '642', '812', '1082', '1442', '1922', '2432', '2562', '3242', '4322', '5762', '7682', '7292', '9722', '10242', '12962'};

    % ===== BEM LAYERS =====
    jPanelVert = gui_river([4,4], [3,15,10,10], 'Number of vertices per layer');
        gui_component('label', jPanelVert, '', 'Best results are obtained with:
outer skull=inner skull

', [], [], [], []);
        % Scalp
        gui_component('label', jPanelVert, 'br', 'Scalp: ', [], [], [], []);
        jComboVertScalp = gui_component('combobox', jPanelVert, 'tab', [], {VertList}, [], [], []);
        jComboVertScalp.setSelectedIndex(8);
        % Outer skull
        gui_component('label', jPanelVert, 'br', 'Outer skull: ', [], [], [], []);
        jComboVertOuter = gui_component('combobox', jPanelVert, 'tab', [], {VertList}, [], [], []);
        jComboVertOuter.setSelectedIndex(8);
        % Inner skull
        gui_component('label', jPanelVert, 'br', 'Inner skull: ', [], [], [], []);
        jComboVertInner = gui_component('combobox', jPanelVert, 'tab', [], {VertList}, [], [], []);
        jComboVertInner.setSelectedIndex(8);
    jPanelNew.add('br hfill', jPanelVert);

    % ===== BEM THICKNESS =====
    jPanelThick = gui_river([4,4], [0,15,12,10], 'Thickness of the layers');
%         gui_component('label', jPanelThick, '', 'Relative values, scaled for each subject
by the distance between brain and skin.

', [], [], [], []);
%         % Scalp-Outer
%         gui_component('label', jPanelThick, 'br', 'Scalp / outer skull: ', [], [], [], []);
%         jTextThickScalp = gui_component('texttime', jPanelThick, 'tab', num2str(BemOptions.thickness(1), '%d'), [], [], [], []);
%         % Outer-Inner
%         gui_component('label', jPanelThick, 'br', 'Outer skull / inner skull: ', [], [], [], []);
%         jTextThickOuter = gui_component('texttime', jPanelThick, 'tab', num2str(BemOptions.thickness(2), '%d'), [], [], [], []);
%         % Inner-Brain
%         gui_component('label', jPanelThick, 'br', 'Inner skull / brain: ', [], [], [], []);
%         jTextThickInner = gui_component('texttime', jPanelThick, 'tab', num2str(BemOptions.thickness(3), '%d'), [], [], [], []);
        gui_component('label', jPanelThick, 'br', 'Skull (mm): ', [], [], [], []);
        jTextThickOuter = gui_component('texttime', jPanelThick, 'tab', num2str(BemOptions.thickness(2), '%d'), [], [], [], []);
    jPanelNew.add('br hfill', jPanelThick);

    % ===== VALIDATION BUTTONS =====
    gui_component('button', jPanelNew, 'br right', 'Cancel', [], [], @ButtonCancel_Callback, []);
    gui_component('button', jPanelNew, [], 'OK', [], [], @ButtonOk_Callback, []);

    % ===== PANEL CREATION =====
    % Return a mutex to wait for panel close
    bst_mutex('create', panelName);
    % Controls list
    ctrl = struct('BemOptions',       BemOptions, ...
                  'jComboVertScalp',  jComboVertScalp, ...
                  'jComboVertOuter',  jComboVertOuter, ...
                  'jComboVertInner',  jComboVertInner, ...
                  'jTextThickOuter',  jTextThickOuter);
%                   'jTextThickScalp',  jTextThickScalp, ...
%                   'jTextThickOuter',  jTextThickOuter, ...
%                   'jTextThickInner',  jTextThickInner);
    % Create the BstPanel object that is returned by the function
    % => constructor BstPanel(jHandle, panelName, sControls)
    bstPanelNew = BstPanel(panelName, jPanelNew, ctrl);
    % Update panel
    UpdatePanel();

%% =================================================================================
%  === INTERNAL CALLBACKS ==========================================================
%  =================================================================================
%% ===== CANCEL BUTTON =====
    function ButtonCancel_Callback(hObject, event)
        % Close panel without saving (release mutex automatically)
        gui_hide(panelName);
    end

%% ===== OK BUTTON =====
    function ButtonOk_Callback(varargin)
        % Release mutex and keep the panel opened
        bst_mutex('release', panelName);
    end

%% ===== UPDATE PANEL =====
    function UpdatePanel(varargin)

    end
end

%% =================================================================================
%  === EXTERNAL CALLBACKS ==========================================================
%  =================================================================================
%% ===== GET PANEL CONTENTS =====
function s = GetPanelContents() %#ok<DEFNU>
    % Get panel controls
    ctrl = bst_get('PanelControls', 'BemOptions');
    % Bem layers
    nvert1 = str2double(char(ctrl.jComboVertScalp.getSelectedItem()));
    nvert2 = str2double(char(ctrl.jComboVertOuter.getSelectedItem()));
    nvert3 = str2double(char(ctrl.jComboVertInner.getSelectedItem()));
    %thick1 = str2double(char(ctrl.jTextThickScalp.getText()));
    thick2 = str2double(char(ctrl.jTextThickOuter.getText()));
    %thick3 = str2double(char(ctrl.jTextThickInner.getText()));
    % Check for errors
    if isnan(nvert1) || isnan(nvert2) || isnan(nvert3) || isnan(thick2)
        error('Invalid values.');
    end
    s.nvert = [nvert1 nvert2 nvert3];
    s.thickness = [ctrl.BemOptions.thickness(1) thick2 ctrl.BemOptions.thickness(3)];
end


function [dat] = read_brainvision_eeg(filename, hdr, begsample, endsample);

% READ_BRAINVISION_EEG reads raw data from an EEG file
% and returns it as a Nchans x Nsamples matrix
%
% Use as
%   dat = read_brainvision_eeg(filename, hdr, begsample, endsample)
% where the header should be first read using read_brainvision_vhdr
%
% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK

% Copyright (C) 2003, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% 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: read_brainvision_eeg.m 945 2010-04-21 17:41:20Z roboos $

if strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_16')
  fid = fopen(filename, 'rb', 'ieee-le');
  fseek(fid, hdr.NumberOfChannels*2*(begsample-1), 'cof');
  [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int16');
  fclose(fid);
  % compute real microvolts using the calibration factor (resolution)
  res = sparse(diag(hdr.resolution));
  dat = res * dat;

elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_32')
  fid = fopen(filename, 'rb', 'ieee-le');
  fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof');
  [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int32');
  fclose(fid);
  % compute real microvolts using the calibration factor (resolution)
  res = sparse(diag(hdr.resolution));
  dat = res * dat;

elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'ieee_float_32')
  fid = fopen(filename, 'rb', 'ieee-le');
  fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof');
  [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'float32');
  fclose(fid);

elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'vectorized') && strcmpi(hdr.BinaryFormat, 'ieee_float_32')
  fid = fopen(filename, 'rb', 'ieee-le');
  fseek(fid, 0, 'eof');
  hdr.nSamples = ftell(fid)/(4*hdr.NumberOfChannels);
  fseek(fid, 0, 'bof');
  numsamples = (endsample-begsample+1);
  for chan=1:hdr.NumberOfChannels
    fseek(fid, (begsample-1)*4, 'cof');                 % skip the first N samples
    [tmp, siz] = fread(fid, numsamples, 'float32');     % read these samples
    fseek(fid, (hdr.nSamples-endsample)*4, 'cof');      % skip the last M samples
    dat(chan,:) = tmp(:)';
  end
  fclose(fid);

elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'multiplexed')
  fid = fopen(filename, 'rt');
  for line=1:(begsample-1)
    % read first lines and discard the data in them
    str = fgets(fid);
  end
  dat = zeros(endsample-begsample+1, hdr.NumberOfChannels);
  for line=1:(endsample-begsample+1)
    str = fgets(fid);           % read a single line with Nchan samples
    str(find(str==',')) = '.';      % replace comma with point
    dat(line,:) = str2num(str);
  end
  fclose(fid);
  % transpose the data
  dat = dat';

elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'vectorized')
  % this is a very inefficient fileformat to read data from, since it requires to
  % read in all the samples of each channel and then select only the samples of interest
  fid = fopen(filename, 'rt');
  dat = zeros(hdr.NumberOfChannels, endsample-begsample+1);
  for chan=1:hdr.NumberOfChannels
    % this is very slow, so better give some feedback to indicate that something is happening
    fprintf('reading channel %d from ascii file to get data from sample %d to %d\n', chan, begsample, endsample);

    str = fgets(fid);             % read all samples of a single channel
    str(find(str==',')) = '.';      % replace comma with point

    if ~isempty(regexp(str(1:10), '[a-zA-Z]', 'once'))
      % the line starts with letters, not numbers: probably it is a channel label
      % find the first number and remove the preceding part
      sel   = regexp(str(1:10), ' [-0-9]');   % find the first number, or actually the last space before the first number
      label = str(1:(sel));                   % this includes the space
      str   = str((sel+1):end);               % keep only the numbers
    end

    % convert the string into numbers and copy the desired samples over
    % into the data matrix
    tmp = str2num(str);
    dat(chan,:) = tmp(begsample:endsample);
  end
  fclose(fid);

else
  error('unsupported sub-fileformat');
end


classdef StiffnessPlaneStressVoigtTensor < SymmetricFourthOrderPlaneStressVoigtTensor ...
                                           & StiffnessDescriptor

end


function t_dmc_element(quiet)
%T_DMC_ELEMENT  Tests for MP.DMC_ELEMENT.

%   MATPOWER
%   Copyright (c) 2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

if nargin < 1
    quiet = 0;
end

% define_constants;
if quiet
    verbose = 0;
else
    verbose = 1;
end

table_class = mp_table_class();

%%  1       2       3       4       5       6
%%  alpha   beta    uid     gamma   delta   epsilon
foo = [ ...
    11      5       1       0.1     9       0
    22      4       2       0.3     3       2
    33      3       3       0.5     7       0
    44      2       4       0.7     5       4
    55      1       5       0.9     1       6
];
baz = {
    'uno', 'one';
    'dos', 'two';
    'tres', 'three';
    'cuatro', 'four';
    'cinco', 'five';
};
d0 = struct('foo', foo, 'bar', struct('baz', {baz}));
ridx1 = 2;
ridx2 = [3;1];

r = [2;4;5];
var_names = {'uid', 'name', 'status', 'source_uid', ...
        'ids', 'twos', 'alpha', 'beta', 'gamma', 'delta', 'epsilon'};
ec = cell(5,1); [ec{:}] = deal('');
vals = {foo(:,3), baz(:,2), ones(5,1), ec, foo(:,3), 2*ones(5,1), ...
    foo(:,1), 10*foo(:,2), 2*foo(:,4), 5*foo(:,5), foo(:,6)};
tab0 = table_class(vals{:}, 'VariableNames', var_names);
tab1 = tab0(r,:); tab1.ids = [1:3]'; tab1.source_uid = r;

t_begin(24, quiet);

%% 1 - dme table rows correspond to original data rows
k = 'A';
t = sprintf('%s : dmce : ', k);
dmce = mp.dmce_test_widget();
t_ok(isa(dmce, 'mp.dmc_element'), [t 'class']);
t_is(dmce.use_r, 0, 12, [t 'dmce.use_r == 0']);

t = sprintf('%s : dme : ', k);
dme = mp.dme_test_widget();
t_ok(isa(dme, 'mp.dm_element'), [t 'class']);
t_ok(isempty(dme.tab), [t 'dme.tab empty']);

t = sprintf('%s : import(dme, d) : ', k);
dme = dmce.import(mp.dme_test_widget(), d0);
t_ok(~isempty(dme.tab), [t 'dme.tab not empty']);
t_ok(isequal(dme.tab, tab0), [t 'dme.tab']);

t = sprintf('%s : export(dme, d) : ', k);
d = struct();
d = dmce.export(dme, d);
ed = d0; ed.bar.baz(:,1) = ed.bar.baz(:,2); [ed.bar.baz{:,2}] = deal([]);
t_ok(isequal(d, ed), [t 'd']);

t = sprintf('%s : import(dme, d, var_names) : ', k);
d = d0; d.foo = d0.foo(:, end:-1:1);    %% reverse columns
tab = tab0; tmp = tab.alpha; tab.alpha = tab.epsilon; tab.epsilon = tmp;
dme = dmce.import(mp.dme_test_widget(), d0);
dme = dmce.import(dme, d, {'alpha', 'epsilon'});
t_ok(isequal(dme.tab, tab), [t 'dme.tab']);

t = sprintf('%s : export(dme, d, var_names) : ', k);
tmp = dme.tab.beta; dme.tab.beta = dme.tab.delta; dme.tab.delta = tmp;
ed = d0; ed.foo(:, [2 5]) = ed.foo(:, [5 2]);
ed.foo(:, 2) = ed.foo(:, 2)/2;
ed.foo(:, 5) = ed.foo(:, 5)*2;
d = dmce.export(dme, d0, {'beta', 'delta'});
t_ok(isequal(d, ed), [t 'd']);

t = sprintf('%s : import(dme, d, var_names, <scalar>) : ', k);
d = d0; d.foo = d0.foo(:, end:-1:1);    %% reverse columns
tab = tab0; tmp = tab.alpha(ridx1); tab.alpha(ridx1) = tab.epsilon(ridx1); tab.epsilon(ridx1) = tmp;
dme = dmce.import(mp.dme_test_widget(), d0);
dme = dmce.import(dme, d, {'alpha', 'epsilon'}, ridx1);
t_ok(isequal(dme.tab, tab), [t 'dme.tab']);

t = sprintf('%s : export(dme, d, var_names, <scalar>) : ', k);
tmp = dme.tab.beta; dme.tab.beta = dme.tab.delta; dme.tab.delta = tmp;
ed = d0; ed.foo(ridx1, [2 5]) = ed.foo(ridx1, [5 2]);
ed.foo(ridx1, 2) = ed.foo(ridx1, 2)/2;
ed.foo(ridx1, 5) = ed.foo(ridx1, 5)*2;
d = dmce.export(dme, d0, {'beta', 'delta'}, ridx1);
t_ok(isequal(d, ed), [t 'd']);

t = sprintf('%s : import(dme, d, var_names, <vector>) : ', k);
d = d0; d.foo = d0.foo(:, end:-1:1);    %% reverse columns
tab = tab0; tmp = tab.alpha(ridx2); tab.alpha(ridx2) = tab.epsilon(ridx2); tab.epsilon(ridx2) = tmp;
dme = dmce.import(mp.dme_test_widget(), d0);
dme = dmce.import(dme, d, {'alpha', 'epsilon'}, ridx2);
t_ok(isequal(dme.tab, tab), [t 'dme.tab']);

t = sprintf('%s : export(dme, d, var_names, <vector>) : ', k);
tmp = dme.tab.beta; dme.tab.beta = dme.tab.delta; dme.tab.delta = tmp;
ed = d0; ed.foo(ridx2, [2 5]) = ed.foo(ridx2, [5 2]);
ed.foo(ridx2, 2) = ed.foo(ridx2, 2)/2;
ed.foo(ridx2, 5) = ed.foo(ridx2, 5)*2;
d = dmce.export(dme, d0, {'beta', 'delta'}, ridx2);
t_ok(isequal(d, ed), [t 'd']);

%% 2 - dme table has r for indexing original data rows
k = 'B';
t = sprintf('%s : dmce : ', k);
dmce = mp.dmce_test_widget();
dmce.use_r = 1;
t_ok(isa(dmce, 'mp.dmc_element'), [t 'class']);
t_is(dmce.use_r, 1, 12, [t 'dmce.use_r == 1']);

t = sprintf('%s : import(dme, d) : ', k);
dme = dmce.import(mp.dme_test_widget(), d0);
t_ok(~isempty(dme.tab), [t 'dme.tab not empty']);
t_ok(isequal(dme.tab, tab1), [t 'dme.tab']);

t = sprintf('%s : export(dme, d) : ', k);
d = d0; d.foo = 0 * d.foo;
d = dmce.export(dme, d);
ed = d0;
ed.foo([1;3], :) = 0 * ed.foo([1;3], :);
ed.bar.baz(r,1) = ed.bar.baz(r,2);
t_ok(isequal(d, ed), [t 'd']);

t = sprintf('%s : import(dme, d, var_names) : ', k);
d = d0; d.foo(:, 1:end-2) = d0.foo(:, end-2:-1:1);  %% reverse columns
d.bar.baz(:, [1 2]) = d.bar.baz(:, [2 1]);          %% reverse columns
tab = tab1;
tmp = tab.alpha;
tab.alpha = tab.gamma / 2;
tab.gamma = tmp * 2;
tab.name = baz(r, 1);
dme = dmce.import(mp.dme_test_widget(), d0);
dme = dmce.import(dme, d, {'alpha', 'name', 'gamma'});
t_ok(isequal(dme.tab, tab), [t 'dme.tab']);

t = sprintf('%s : export(dme, d, var_names) : ', k);
tmp = dme.tab.beta; dme.tab.beta = dme.tab.delta; dme.tab.delta = tmp;
d = d0; d.foo = 0 * d.foo;
[d.bar.baz{:}] = deal('');
ed = d;
ed.foo(r, [2;5]) = d0.foo(r, [5;2]) * [0.5 0; 0 2];
ed.bar.baz(r,1) = d0.bar.baz(r,1);
d = dmce.export(dme, d, {'beta', 'delta', 'name'});
t_ok(isequal(d, ed), [t 'd']);

t = sprintf('%s : import(dme, d, var_names, <scalar>) : ', k);
d = d0; d.foo(:, 1:end-2) = d0.foo(:, end-2:-1:1);  %% reverse columns
d.bar.baz(:, [1 2]) = d.bar.baz(:, [2 1]);          %% reverse columns
tab = tab1;
tmp = tab.alpha(ridx1);
tab.alpha(ridx1) = tab.gamma(ridx1) / 2;
tab.gamma(ridx1) = tmp * 2;
tab.name(ridx1) = baz(r(ridx1), 1);
dme = dmce.import(mp.dme_test_widget(), d0);
dme = dmce.import(dme, d, {'alpha', 'name', 'gamma'}, ridx1);
t_ok(isequal(dme.tab, tab), [t 'dme.tab']);

t = sprintf('%s : export(dme, d, var_names, <scalar>) : ', k);
tmp = dme.tab.beta; dme.tab.beta = dme.tab.delta; dme.tab.delta = tmp;
d = d0; d.foo = 0 * d.foo;
[d.bar.baz{:}] = deal('');
ed = d;
ed.foo(r(ridx1), [2;5]) = d0.foo(r(ridx1), [5;2]) * [0.5 0; 0 2];
ed.bar.baz(r(ridx1),1) = d0.bar.baz(r(ridx1),1);
d = dmce.export(dme, d, {'beta', 'delta', 'name'}, ridx1);
t_ok(isequal(d, ed), [t 'd']);

t = sprintf('%s : import(dme, d, var_names, <vector>) : ', k);
d = d0; d.foo(:, 1:end-2) = d0.foo(:, end-2:-1:1);  %% reverse columns
d.bar.baz(:, [1 2]) = d.bar.baz(:, [2 1]);          %% reverse columns
tab = tab1;
tmp = tab.alpha(ridx2);
tab.alpha(ridx2) = tab.gamma(ridx2) / 2;
tab.gamma(ridx2) = tmp * 2;
tab.name(ridx2) = baz(r(ridx2), 1);
dme = dmce.import(mp.dme_test_widget(), d0);
dme = dmce.import(dme, d, {'alpha', 'name', 'gamma'}, ridx2);
t_ok(isequal(dme.tab, tab), [t 'dme.tab']);

t = sprintf('%s : export(dme, d, var_names, <vector>) : ', k);
tmp = dme.tab.beta; dme.tab.beta = dme.tab.delta; dme.tab.delta = tmp;
d = d0; d.foo = 0 * d.foo;
[d.bar.baz{:}] = deal('');
ed = d;
ed.foo(r(ridx2), [2;5]) = d0.foo(r(ridx2), [5;2]) * [0.5 0; 0 2];
ed.bar.baz(r(ridx2),1) = d0.bar.baz(r(ridx2),1);
d = dmce.export(dme, d, {'beta', 'delta', 'name'}, ridx2);
t_ok(isequal(d, ed), [t 'd']);

t_end;


%   CLASS Meteo_Network
% =========================================================================
%
% DESCRIPTION
%   Class to store and manage a network of meteo station
%
% EXAMPLE
%   settings = Meteo_Network();
%
% FOR A LIST OF CONSTANTs and METHODS use doc Meteo_Data
%
% REFERENCE

%--------------------------------------------------------------------------
%               ___ ___ ___
%     __ _ ___ / __| _ | __|
%    / _` / _ \ (_ |  _|__ \
%    \__, \___/\___|_| |___/
%    |___/                    v 1.0RC1
%
%--------------------------------------------------------------------------
%  Copyright (C) 2021 Geomatics Research & Development srl (GReD)
%  Written by:        Andrea Gatti, Giulio Tagliaferro ...
%  Contributors:      Andrea Gatti, Giulio Tagliaferro ...
%  A list of all the historical goGPS contributors is in CREDITS.nfo
%--------------------------------------------------------------------------
%
%    This program is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    This program is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this program.  If not, see <http://www.gnu.org/licenses/>.
%----------------------------------------------------------------------------------------------
classdef Meteo_Network < handle
    properties
        mds % list of meteo data
        log % handfle of logger
    end
    %% METHOD CREATOR
    % ==================================================================================================================================================
    methods (Static)
        % Concrete implementation.  See Singleton superclass.
        function this = Meteo_Network()
            this.log = Core.getLogger();
        end
    end

    %% METHODS UI
    % ==================================================================================================================================================
    methods (Static, Access = public)
        function ok_go = openGUI()
            ok_go = gui_goGPS;
        end
    end

    methods (Access = public)
        function initSession(this, date_start, date_stop)
            % Load all the metereological data
            %
            % SYNTAX
            % this.initSession(data_start, data_stop)

            this.mds = [];
            % load all meteo file present in current settings
            state = Core.getCurrentSettings();
            fnames = state.getMetFileName(date_start, date_stop);
            this.initFromFileList(fnames)
        end

        function initFromFileList(this, file_name_list)
            % Load metereological data directly from file list
            %
            % INPUT
            %   file_name_list: two level cells, first level station second level days
            %
            % SYNTAX
            %   this.initFromFileList(file_name_list)

            n_stations = numel(file_name_list);
            for  i = 1 : n_stations
                n_sss = numel(file_name_list{i});
                for  s = 1 : n_sss
                    if ~isempty(File_Name_Processor.getFileName(file_name_list{i}{s}))
                        if ~exist(file_name_list{i}{s}, 'file')
                            this.log.addWarning(sprintf('Skipping %s - file not found', file_name_list{i}{s}));
                        else
                            md = Meteo_Data(file_name_list{i}{s});
                            if md.isValid()
                                % md.setMaxBound(0);
                                if length(this.mds) < i
                                    this.mds = [this.mds; md];
                                else
                                    this.mds(i).inject(md);
                                end
                            end
                        end
                    end
                end
            end
        end

        function md = getVMS(this, name, xyz, time)
            % Get Virtual Meteo Station
            %
            % INPUT
            %   name    name of the new Meteo_Data virtual station
            %   xyz     coordinates of the new meteo station
            %   time    time of interpolation
            %
            %
            % OUTPUT
            %   md      virtual Meteo_Data station generated at xyz coordinates
            %
            % SYNTAX
            %   md = this.getVMS(name, xyz, time)
            %
            % EXAMPLE
            %   [x, y, z, amsl] = station(1).getLocation();
            %   md1 = this.getVMS('test', [x y z], station(1).getObsTime)
            md = Meteo_Data.getVMS( name, xyz, time, this.mds);
        end
    end

end


classdef InteriorSubCellsConnecComputer < handle

    properties (GetAccess = public, SetAccess = private)
        connec
        xCoordsIso
        cellContainingSubcell
    end

    properties (Access = private)
        isSubCellInterior
        subCellCases
        allSubCellsConnec
        xNodesInSubCells
    end

    properties (Access = private)
        localCells
        allSubCellsConnecParams
        cutElems
        nSubCellsByElem
    end

    methods (Access = public)

        function obj = InteriorSubCellsConnecComputer(cParams)
            obj.init(cParams);
            obj.compute();
        end

    end

    methods (Access = private)

        function init(obj,cParams)
            obj.allSubCellsConnecParams = cParams.allSubCellsConnecParams;
            obj.cutElems                = cParams.cutElems;
            obj.nSubCellsByElem         = cParams.nSubCellsByElem;
            obj.isSubCellInterior       = cParams.isSubCellInterior;
        end

        function compute(obj)
            obj.computeAllSubCellsConnec();
            obj.computeLocalCellContainingSubCell();
            obj.computeConnec();
            obj.computeXcoordsIso();
            obj.computeCellContainingSubCell();
        end

        function computeAllSubCellsConnec(obj)
            s = obj.allSubCellsConnecParams;
            a = AllSubCellsConnecComputer(s);
            a.compute();
            obj.allSubCellsConnec = a.allSubCellsConnec;
            obj.xNodesInSubCells  = a.xNodesInSubCells;
        end

        function cells = computeLocalCellContainingSubCell(obj)
            isInterior = obj.isSubCellInterior;
            nCutElem   = size(isInterior,2);
            localSubCellsInCell = repmat(1:nCutElem,obj.nSubCellsByElem,1);
            cells = localSubCellsInCell(isInterior);
            obj.localCells = cells;
        end

        function computeConnec(obj)
            allConnec  = obj.allSubCellsConnec;
            isInterior = obj.isSubCellInterior(:);
            obj.connec = allConnec(isInterior,:);
        end

        function computeXcoordsIso(obj)
            isInterior = obj.isSubCellInterior(:);
            x = obj.xNodesInSubCells;
            nDim = size(x,3);
            nElem = sum(isInterior);
            nNode = size(x,1);
            obj.xCoordsIso = zeros(nDim,nNode,nElem);
            for idim = 1:nDim
                obj.xCoordsIso(idim,:,:) = x(:,isInterior,idim);
            end
        end

        function computeCellContainingSubCell(obj)
            localToGlobalCut = obj.cutElems;
            lCells  = obj.localCells;
            globalCell = localToGlobalCut(lCells);
            obj.cellContainingSubcell = globalCell;
        end

    end

end


 function out = fatrix2_subsref_dot(st, args)
%function out = fatrix2_subsref_dot(st, args)
% handle subscript references like ob.ref or ob.ref(arg[s])
% This will called from ../subsref with struct(ob)
% and it will have arg(1).type = '.'
% Based on @strum/subsref
% Copyright 2006-1-19, Jeff Fessler, University of Michigan

%if args(1).type ~= '.'
%	error 'only ob.data and ob.meth(args) done'
%end

name = args(1).subs;
%printm('here, name=%s', name)

switch name
case 'imask_array'
	out = fatrix2_imask_array(st);
	return

case 'omask_array'
	out = fatrix2_omask_array(st);
	return

end

% ob.name
if isfield(st, name)
	if length(args) == 1
		out = st.(name);
	else
		out = subsref(st.(name), args(2:end));
	end

% ob.name or ob.name(arg[s]), where name is in meth field
elseif isfield(st.meth, name)
	fun = st.meth.(name); % function handle for method
	if length(args) == 1
		out = fun(st.arg);
	elseif length(args) == 2
		out = fun(st.arg, args(2).subs{:});
	else
		printm('unknown subs')
		keyboard
	end

% ob.name, where name is in data field 'arg' (last resort)
elseif isfield(st.arg, name)
	out = st.arg.(name);
	if length(args) > 1

		% ob.name{:} does not work properly because there seems
		% to be no way to return an arbitrary number of arguments
		% (in a list) to the caller.
		% This is unfortunate because
		% a.b = {1,2} and a.b{:} works for ordinary structures.
% todo: see this solution involving numel()
% http://www.mathworks.com/support/solutions/data/1-1ABOD.html?solution=1-1ABOD
		if iscell(out) && ...
		(isequal(args(2).subs, {':'}) || length(args(2).subs{1}) > 1)
			warn 'instead of strum.data{:} etc., use two steps:'
			warn 'tmp = strum.data; tmp{:} or tmp{1:end} etc.'
			fail 'strum.data{:} etc. unsupported thanks to matlab'
		end

		% fix: strum1.strum2.plot() does not work here
		out = subsref(out, args(2:end));
	end

else
	disp(st)
	fail(['unknown field name: ' name])
end


function F_cell = flip_vec(F_cell)

chkarg(istypesizeof(F_cell, 'complexcell', [1 Axis.count]) || istypesizeof(F_cell, 'complexcell', [Axis.count 1]), ...
	'"F_cell" should be length-%d row or column cell array whose each element is array with complex elements.', Axis.count);

for w = Axis.elems
	F_cell{w} = flip_array(F_cell{w});
end


function [F] = registerjacobian(F)
%REGISTERJACOBIAN Register jacobians to all constraints

F = flatten(F);
Counter = length(F.LMIid);
for i = 1:Counter
    switch F.clauses{i}.type
        case {1,2,3}
            Fi = F.clauses{i}.data;
            F.clauses{i}.data = registerjacobian(Fi);
        otherwise
    end
end


function varargout = main(varargin)
% MAIN M-file for main.fig
%      MAIN, by itself, creates a new MAIN or raises the existing
%      singleton*.
%
%      H = MAIN returns the handle to a new MAIN or the handle to
%      the existing singleton*.
%
%      MAIN('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in MAIN.M with the given input arguments.
%
%      MAIN('Property','Value',...) creates a new MAIN or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before main_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to main_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help main

% Last Modified by GUIDE v2.5 06-Mar-2013 13:59:04

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @main_OpeningFcn, ...
                   'gui_OutputFcn',  @main_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 main is made visible.
function main_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 main (see VARARGIN)

% Choose default command line output for main
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

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

% --- Outputs from this function are returned to the command line.
function varargout = main_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
varargout{1} = handles.output;

% --- Executes on button press in Browse_Image.
function Browse_Image_Callback(hObject, eventdata, handles)
% hObject    handle to Browse_Image (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.output = hObject;
[filename,pathname]=uigetfile('*.jpg');
if ~filename
    errordlg('Select an Image File.');
     return;
end
a=imread(strcat(pathname,filename));
handles.my_data=a;
guidata(hObject, handles);

% --- Executes on button press in Press_for_haar.
function Press_for_haar_Callback(hObject, eventdata, handles)
% hObject    handle to Press_for_haar (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
a=handles.my_data;
[v,w]=haaar(a);
handles.my_out=v;
handles.w=w;
guidata(hObject,handles);
axes(handles.image_out);
axis off;
axes(handles.image_out);
imshow(handles.my_out);

% --- Executes on button press in press_for_LL_pixels.
function press_for_LL_pixels_Callback(hObject, eventdata, handles)
% hObject    handle to press_for_LL_pixels (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.my_out=handles.w;
axes(handles.image_out);
axis off;
axes(handles.image_out);
imshow(handles.my_out);

% --- Executes on button press in Close.
function Close_Callback(hObject, eventdata, handles)
% hObject    handle to Close (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
close all;
clc;
clear all;


function a = read_cor(fname)
% a = read_cor(fname)

%
% read_cor.m
%
% Original Author: Bruce Fischl
% CVS Revision Info:
%    $Author: nicks $
%    $Date: 2011/03/02 00:04:12 $
%    $Revision: 1.3 $
%
% Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH"
%
% Terms and conditions for use, reproduction, distribution and contribution
% are found in the 'FreeSurfer Software License Agreement' contained
% in the file 'LICENSE' found in the FreeSurfer distribution, and here:
%
% https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferSoftwareLicense
%
% Reporting: freesurfer@nmr.mgh.harvard.edu
%

a = zeros(256, 256, 256);

for i=1:256
%	disp(i);
	fname1 = sprintf('%s/COR-%03d', fname, i);
	fid = fopen(fname1, 'r');
	a(:, :, i) = fread(fid, [256 256], 'uchar');
	fclose(fid);
end

% eof


%% _getAllFiles_ demo
% The _getAllFiles_ function recursively collects a list of files from a
% folder tree, allowing you to specify the selection criteria for which
% files are collected and how they are formatted. For these examples, we'll
% be using the main MATLAB toolbox path.
%%

rootPath = 'C:\Program Files\MATLAB\R2016b\toolbox\matlab';
format compact

%% The 'FileFilter' option
% We can specify a
% <https://www.mathworks.com/help/matlab/matlab_prog/regular-expressions.html
% regular-expression> pattern to filter the file names on, collecting a
% list of files that match. Here's an example that uses the 'FileFilter'
% option to recursively find every file with a '.m' extension:

fileList = getAllFiles(rootPath, 'FileFilter', '\.m$');
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');

%%
% It's a pretty long list, so I've only shown the first 5 files it finds.
% Notice they are listed with the full path prepended by default.

%%
% If you have multiple match expressions to filter on, you can use
% <https://www.mathworks.com/help/matlab/matlab_prog/regular-expressions.html#f0-42884
% grouping operators> to include them all in one expression. For example,
% this will find every '.jpg', '.bmp', and '.tif' file:

fileList = getAllFiles(rootPath, 'FileFilter', '\.(jpg|bmp|tif)$');
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');

%% The 'Depth' option
% If we don't want to search quite so far down the folder tree, we can
% limit the search depth with the 'Depth' option. Let's see how many '.m'
% files are in the root folder:

fileList = getAllFiles(rootPath, 'FileFilter', '\.m$', 'Depth', 0);
fprintf('%d files found.\n', size(fileList, 1));

%%
% Looks like none are. They are all contained in subfolders. Let's see how
% many are located in just the immediate subfolders of the root folder:

fileList = getAllFiles(rootPath, 'FileFilter', '\.m$', 'Depth', 1);
fprintf('%d files found.\n', size(fileList, 1));

%% The 'PrependPath' option
% Maybe we just want the file names, but don't care about the absolute
% paths. In this case, we just set the 'PrependPath' option to _false_:

fileList = getAllFiles(rootPath, 'FileFilter', '\.m$', ...
                                 'PrependPath', false);
fprintf('%d files found.\n', size(fileList, 1));
fprintf('%s\n', fileList{1:5}, '...');

%% The 'ValidateFcn' option
% Sometimes we might want to select files based on a more complicated
% criteria than just what's in their names. In this case, we can use the
% 'ValidateFcn' option to specify a function that is to be run on each file
% found. This function should accept as input a structure of the form
% returned by the |dir| function and return a logical value (|true| to
% collect it in the list, |false| to ignore it). First, let's find all the
% '.png' files:

fileList = getAllFiles(rootPath, 'FileFilter', '\.png$');
fprintf('%d files found.\n', size(fileList, 1));

%%
% Now, we can specify an anonymous function that gets the byte size of each
% file and returns |true| for only those greater than 250KB:

bigFcn = @(s) (s.bytes > 512^2);
fileList = getAllFiles(rootPath, 'FileFilter', '\.png$', ...
                                 'ValidateFcn', bigFcn);
fprintf('%s\n', fileList{:});

%%
% Just the one.


classdef ConstraintManager < handle

    properties (SetAccess = private)
        C_equality;
        C_inequality;
    end

    methods (Access = public)

        function obj = ConstraintManager()
            obj.C_equality = containers.Map();
            obj.C_inequality = containers.Map();
        end

        function add_eq_constraint(obj, key, C_eq1, C_eq2)
            obj.C_equality(key) =  {C_eq1, C_eq2};
        end

        function add_ineq_constraint(obj, key, C_ineq1, C_ineq2)
            obj.C_inequality(key) =  {C_ineq1, C_ineq2};
        end

        function remove_eq_constraint(obj, key)
            remove(obj.C_equality, key);
        end

        function remove_ineq_constraint(obj, key)
            remove(obj.C_inequality, key);
        end

        function [C_eq1, C_eq2] = combine_all_eq_constraints(obj)
            C_eq_array = values(obj.C_equality);
            C_eq1 = [];
            C_eq2 = [];
            for i = 1:numel(C_eq_array)
                C_eq1 = [C_eq1; C_eq_array{i}{1}];
                C_eq2 = [C_eq2; C_eq_array{i}{2}];
            end
        end

        function [C_ineq1, C_ineq2] = combine_all_ineq_constraints(obj)
            C_ineq_array = values(obj.C_inequality);
            C_ineq1 = [];
            C_ineq2 = [];
            for i = 1:numel(C_ineq_array)
                C_ineq1 = [C_ineq1; C_ineq_array{i}{1}];
                C_ineq2 = [C_ineq2; C_ineq_array{i}{2}];
            end
        end
    end
end


%%% Note: run the 'GenerateData_model_64_25_Res_Bnorm_Adam.m' to generate
%%% training data first.

%%%-------------------------------------------------------------------------
%%% configuration
%%%-------------------------------------------------------------------------
opts.modelName        = 'model_64_25_Res_Bnorm_Adam'; %%% model name
opts.learningRate     = [logspace(-3,-3,30) logspace(-4,-4,20)];%%% you can change the learning rate
opts.batchSize        = 128; %%% default
opts.gpus             = [1]; %%% this code can only support one GPU!

%%% solver
opts.solver           = 'Adam';

opts.gradientClipping = false; %%% Set 'true' to prevent exploding gradients in the beginning.
opts.expDir      = fullfile('data', opts.modelName);
opts.imdbPath    = fullfile(opts.expDir, 'imdb.mat');

%%%-------------------------------------------------------------------------
%%%   Initialize model and load data
%%%-------------------------------------------------------------------------
%%%  model
net  = feval(['DnCNN_init_',opts.modelName]);

%%%  load data
imdb = load(opts.imdbPath) ;

%%%-------------------------------------------------------------------------
%%%   Train
%%%-------------------------------------------------------------------------

[net, info] = DnCNN_train(net, imdb, ...
    'expDir', opts.expDir, ...
    'learningRate',opts.learningRate, ...
    'solver',opts.solver, ...
    'gradientClipping',opts.gradientClipping, ...
    'batchSize', opts.batchSize, ...
    'modelname', opts.modelName, ...
    'gpus',opts.gpus) ;


classdef SmoothingRectangleVademecum < handle

    properties (Access = private)
        outPutPath
        smoothVad
        nonSmoothVad
        difDB

        firstVademecum
        secondVademecum
    end

    methods (Access = public)

        function obj = SmoothingRectangleVademecum()
            obj.init();
            obj.smoothVad    = obj.computeVademecum(obj.firstVademecum);
            obj.nonSmoothVad = obj.computeVademecum(obj.secondVademecum);
            obj.postprocessDifVademecum();
        end

    end

    methods (Access = private)

        function init(obj)
            obj.createOutPutPath();
            obj.firstVademecum = 'SuperEllipseQ2';
            %obj.firstVademecum = 'SuperEllipseQOptAnalytic';
            obj.secondVademecum = 'SuperEllipseQMax';
        end

        function createOutPutPath(obj)
            firstPart  = fullfile('/home','alex');
            secondPart = fullfile('git-repos','MicroStructurePaper','Other');
            obj.outPutPath = fullfile(firstPart,secondPart);
        end

        function vc = computeVademecum(obj,fileName)
            d.fileName = fileName;
            d.outPutPath = fullfile(obj.outPutPath,[d.fileName,'/']);
            vc = VademecumComputerAndPlotter(d);
            vc.compute();
        end

        function postprocessDifVademecum(obj)
            fV = obj.firstVademecum;
            sV = obj.secondVademecum;
            folderPath = fullfile(obj.outPutPath,['DifferenceFrom',fV,'to',sV],'/');
            mkdir(folderPath);
            d.fileName   = 'ReactangleDifference';
            d.outPutPath = folderPath;
            d.smoothVD   = obj.smoothVad.vademecumData;
            d.smoothVD.feasibleIndex = obj.smoothVad.getFeasibleIndex();
            d.nonSmoothVD = obj.nonSmoothVad.vademecumData;
            d.nonSmoothVD.feasibleIndex = obj.nonSmoothVad.getFeasibleIndex();
            vc = VademecumDifferenceComputerAndPlotter(d);
            vc.compute();
        end

    end

end


function obj = updateSurfaceplot(obj, surfaceIndex)

%-AXIS INDEX-%
axIndex = obj.getAxisIndex(obj.State.Plot(surfaceIndex).AssociatedAxis);

%-CHECK FOR MULTIPLE AXES-%
[xsource, ysource] = findSourceAxis(obj,axIndex);

%-SURFACE DATA STRUCTURE- %
image_data = get(obj.State.Plot(surfaceIndex).Handle);

%-AXIS DATA-%
eval(['xaxis = obj.layout.xaxis' num2str(xsource) ';']);
eval(['yaxis = obj.layout.yaxis' num2str(ysource) ';']);

%-------------------------------------------------------------------------%

%-surface xaxis-%
obj.data{surfaceIndex}.xaxis = ['x' num2str(xsource)];

%-------------------------------------------------------------------------%

%-surface yaxis-%
obj.data{surfaceIndex}.yaxis = ['y' num2str(ysource)];

%-------------------------------------------------------------------------%

% check for 3D
if any(nonzeros(image_data.ZData))

    %-surface type-%
    obj.data{surfaceIndex}.type = 'surface';

    %---------------------------------------------------------------------%

    %-surface x-%
    obj.data{surfaceIndex}.x = image_data.XData;

    %---------------------------------------------------------------------%

    %-surface y-%
    obj.data{surfaceIndex}.y = image_data.YData;

    %---------------------------------------------------------------------%

    %-surface z-%
    obj.data{surfaceIndex}.z = image_data.ZData;

else

    %-surface type-%
    obj = updateImage(obj, surfaceIndex);

    %-surface x-%
    obj.data{surfaceIndex}.x = image_data.XData(1,:);

    %-surface y-%
    obj.data{surfaceIndex}.y = image_data.YData(:,1);
end

%-------------------------------------------------------------------------%

%-surface name-%
obj.data{surfaceIndex}.name = image_data.DisplayName;

%-------------------------------------------------------------------------%

%-surface showscale-%
obj.data{surfaceIndex}.showscale = false;

%-------------------------------------------------------------------------%

%-surface visible-%
obj.data{surfaceIndex}.visible = strcmp(image_data.Visible,'on');

%-------------------------------------------------------------------------%

leg = get(image_data.Annotation);
legInfo = get(leg.LegendInformation);

switch legInfo.IconDisplayStyle
    case 'on'
        showleg = true;
    case 'off'
        showleg = false;
end

obj.data{surfaceIndex}.showlegend = showleg;

%-------------------------------------------------------------------------%

end


function L=intesselation(X,TES,XI)

t = tsearchn(X,TES,XI);
L=~isnan(t);

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


%
%       HDR Toolbox demo 5:
%	   1) Load "Bottles_Small.hdr" HDR image
%      2) Activate the Interactive HDR Visualization tool
%      3) Write a .png file with the latest clicked exposure using
%      InteractiveHDRVis
%
%       Author: Francesco Banterle
%       Copyright June 2012 (c)
%
%
clear all;

disp('1) Load "Bottles_Small.hdr" HDR image');
img = hdrimread('demos/Bottles_Small.hdr');

disp('2) Activate the Interactive HDR Visualization tool');
[img_cur_exp, exposure] = AExposureGUI(img);

disp('3)  Write a .png file with the latest clicked exposure using InteractiveHDRVis');
imwrite(GammaTMO(img_cur_exp, 2.2, 0.0, 0), 'demos/output/Venice01_int_vis.png');


function showargs(funcname)
% Show arguments of an argument-aware function with their descriptions
% Usage: showargs funcname

% query arguments
args = arg_report('lean',str2func(funcname));

% print report
fprintf('Arguments of funcname: \n');
for a=args
    if length(a.names) > 1
        name = a.names{2};
    else
        name = a.names{1};
    end
    fprintf(' %s -- %s (%s,%s)\n',name, a.help{1}, a.type, a.shape);
end


function out=isreal(x)

s=builtin('size',x);
out=true;
sx=prod(s);
for ii=1:sx
 ival=x(ii).ival;
 if any(ival~='0')
  out=false;
  break;
 end
end


function im = bbox_draw(im,boxes,c,t)

% copied from Ross Girshick
% Fast R-CNN
% Copyright (c) 2015 Microsoft
% Licensed under The MIT License [see LICENSE for details]
% Written by Ross Girshick
% --------------------------------------------------------
% source: https://github.com/rbgirshick/fast-rcnn/blob/master/matlab/showboxes.m
%
%
% Fast R-CNN
%
% Copyright (c) Microsoft Corporation
%
% All rights reserved.
%
% MIT License
%
% Permission is hereby granted, free of charge, to any person obtaining a
% copy of this software and associated documentation files (the "Software"),
% to deal in the Software without restriction, including without limitation
% the rights to use, copy, modify, merge, publish, distribute, sublicense,
% and/or sell copies of the Software, and to permit persons to whom the
% Software is furnished to do so, subject to the following conditions:
%
% The above copyright notice and this permission notice shall be included
% in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
% OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
% ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
% OTHER DEALINGS IN THE SOFTWARE.

image(im);
axis image;
axis off;
set(gcf, 'Color', 'white');

if nargin<3
  c = 'r';
  t = 2;
end

s = '-';
if ~isempty(boxes)
    x1 = boxes(:, 1);
    y1 = boxes(:, 2);
    x2 = boxes(:, 3);
    y2 = boxes(:, 4);
    line([x1 x1 x2 x2 x1]', [y1 y2 y2 y1 y1]', ...
        'color', c, 'linewidth', t, 'linestyle', s);
    for i = 1:size(boxes, 1)
        text(double(x1(i)), double(y1(i)) - 2, ...
            sprintf('%.4f', boxes(i, end)), ...
            'backgroundcolor', 'b', 'color', 'w', 'FontSize', 10);
    end
end
end


function a = full(a)
%FULL         Convert slope to full
%

% written  04/06/04     S.M. Rump
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  a.r = full(a.r);
  a.s = full(a.s);


function D = meeg(varargin)
% Function for creating meeg objects.
% FORMAT m = meeg(varargin)
%
% SPM8 format consists of a binary memory - mapped data file and a header
% mat file.
%
% The header file will contain an object of class meeg called D. All
% information other than data is contained in this object and access to the
% data is via methods of the object. Also, arbitrary data can be stored
% inside the object if their field names do not conflict with existing
% methods' names.
%
% The following is a description of the internal implementation of meeg.
%
% Fields of meeg:
% .type - type of data in the file: 'continuous', 'single', 'evoked'
% .Fsample - sampling rate
% .data - substruct containing the information related to the bimary data
% file and memory mapping.
%
%   Subfields of .data
%       .y - reference to the data file_array
%       .fnamedat - name of the .dat file
%       .datatype - type of the data for file_array
%
%
% .Nsamples - length of the trial (whole data if the file is continuous).
% .timeOnset - the peri-stimulus time of the first sample in the trial (in sec)
%
% .fname, .path - strings added by spm_eeg_load to keep track of where a
%                 header struct was loaded from.
%
% .trials - this describes the segments of the epoched file and is also a
%           structure array.
%
%   Subfields of .trials
%
%       .label - user-specified string for the condition
%       .onset - time of the first sample in seconds in terms of the
%                original file
%       .bad - 0 or 1 flag to allow rejection of trials.
%       .repl - for epochs that are averages - number of replications used
%               for the average.
%       .events - this is a structure array describing events related to
%                 each trial.
%
%           Subfields of .events
%
%           .type - string (e.g. 'front panel trigger')
%           .value - number or string, can be empty (e.g. 'Trig 1').
%           .time - in seconds in terms of the original file
%           .duration - in seconds
%
% .channels - This is a structure array which is a field of meeg.
%             length(channels) should equal size(.data.y, 1) and the order
%             must correspond to the order of channels in the data.
%
%   Subfields of .channels
%
%       .label - channel label which is always a string
%       .type - a string, possible values - 'MEG', 'EEG', 'VEOG', 'HEOG',
%               'EMG' ,'LFP' etc.
%       .units - units of the data in the channel.
%       .bad - 0 or 1 flag to mark channels as bad.
%       .X_plot2D, .Y_plot2D - positions on 2D plane (formerly in ctf). NaN
%                              for channels that should not be plotted.
%
% .sensors
%
%
%   Subfields of .sensors (optional)
%       .meg - struct with sensor positions for MEG (subfields: .pnt .ori .tra .label)
%       .eeg - struct with sensor positions for MEG (subfields: .pnt .tra .label)
%
% .fiducials - headshape and fiducials for coregistration with sMRI
%
%   Subfiels of .fiducials (optional)
%       .pnt - headshape points
%       .fid.pnt - fiducial points
%       .fid.label - fiducial labels
%
% .artifacts - structure array with fields .start and .stop expressed in
%              seconds in original file time.
%
% .history - structure array describing commands that modified the file.
%
%   Subfields of .history:
%
%       .function - string, the function name
%       .arguments - cell array, the function arguments
%       .time - when function call was made
%
% .other - structure used to store other information bits, not fitting the
%          object structure at the moment,
%       for example:
%       .inv - structure array corresponding to the forw/inv problem in MEEG.
%       .ival - index of the 'inv' solution currently used.
%
% ______________________________________________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: meeg.m 3940 2010-06-21 12:51:19Z christophe $

if nargin == 1
    if isstruct(varargin{1})
        [OK D] = checkmeeg(varargin{1}, 'basic');
        if OK
            D  = class(D, 'meeg');
        else
            error('Struct not fit for conversion to meeg');
        end
        return;
    elseif isa(varargin{1},'meeg'),
        D = varargin{1};
        return;
    end;
end;

D          = [];
D.Nsamples = 0;
[res D]    = checkmeeg(D);
D          = class(D, 'meeg');