function diagnostic = solvesdp(varargin)
%SOLVESDP Obsolete command, please use OPTIMIZE

persistent CACHED_SOLVERS
persistent allsolvers
persistent EXISTTIME
persistent NCHECKS

yalmiptime = clock; % Let us see how much time we spend

% *********************************
% CHECK INPUT
% *********************************
nargin = length(varargin);

% First check of objective for early transfer to multiple solves
if nargin>=2
    if isa(varargin{2},'double')
        varargin{2} = [];
    elseif isa(varargin{2},'sdpvar') && numel(varargin{2})>1
        % Several objectives
        diagnostic = solvesdp_multiple(varargin{:});
        return
    end
end

% Early jump to bisection solver
if nargin >= 3
    if isa(varargin{3},'struct')
        if isfield(varargin{3},'solver')
            if isequal(varargin{3}.solver,'bisection')
                if any(is(varargin{1},'sos'))
                    [F_sos,h_sos] = compilesos(varargin{1},varargin{2},varargin{3});
                    varargin{1} = F_sos;
                    varargin{2} = h_sos;
                end
                diagnostic = bisection(varargin{:});
                return
            end
        end
    end
end

if nargin<1
    help solvesdp
    return
else
    F = varargin{1};
    if isa(F,'constraint')
        F = lmi(F);
    end
    if isa(F,'lmi')
        F = flatten(F);
    end

    if isa(F,'sdpvar')
        % We do allow sloppy coding of logic constraints, i.e writing a
        % constraints as [a|b true(a)]
        Fnew = [];
        for i = 1:length(F)
            if length(getvariables(F(i)))>1
                Fnew = nan;
                break
            end
            operator = yalmip('extstruct',getvariables(F(i)));
            if isempty(operator)
                Fnew = nan;
                break
            end
            if length(operator)>1
                Fnew = nan;
                break
            end
            if ~strcmp(operator.fcn,'or')
                Fnew = nan;
                break
            end
            Fnew = Fnew + (true(F(i)));
        end
        if isnan(Fnew)
            error('First argument (F) should be a constraint object.');
        else
            F = Fnew;
        end
    elseif isempty(F)
        F = lmi([]);
    elseif ~isa(F,'lmi')
        error('First argument (F) should be a constraint object.');
    end
end

if nargin>=2
    h = varargin{2};
    if isa(h,'double')
        h = [];
    end
    if ~(isempty(h) | isa(h,'sdpvar') | isa(h,'logdet') |  isa(h,'ncvar'))
        if isa(h,'struct')
            error('Second argument (the objective function h) should be an sdpvar or logdet object (or empty). It appears as if you sent an options structure in the second argument.');
        else
            error('Second argument (the objective function h) should be an sdpvar or logdet object (or empty).');
        end
    end
    if isa(h,'logdet')
        logdetStruct.P     = getP(h);
        logdetStruct.gain  = getgain(h);
        h = getcx(h);
        if isempty(F)
            F = ([]);
        end
    else
        logdetStruct = [];
    end
else
    logdetStruct = [];
    h = [];
end

if ~isempty(F)
    if any(is(F,'sos'))
        diagnostic = solvesos(varargin{:});
        return
    end
end

if isa(h,'sdpvar')
    if is(h,'complex')
        error('Complex valued objective does not make sense.');
    end
end

if nargin>=3
    options = varargin{3};
    if ~(isempty(options) | isa(options,'struct'))
        error('Third argument (options) should be an sdpsettings struct (or empty).');
    end
    if isempty(options)
        options = sdpsettings;
    end
else
    options = sdpsettings;
end
options.solver = lower(options.solver);

% If user has logdet term, but no preference on solver, we try to hook up
% with SDPT3 if possible.
if ~isempty(logdetStruct)
    if strcmp(options.solver,'')
     %   options.solver = 'sdpt3,*';
    end
end

% Call chance solver?
% if length(F) > 0
%     rand_declarations = is(F,'random');
%     if any(rand_declarations)
%     %    diagnostic = solverandom(F(find(~rand_declarations)),h,options,recover(getvariables(sdpvar(F(find(unc_declarations))))));
%         return
%     end
% end

% Call robust solver?
if length(F) > 0
    unc_declarations = is(F,'uncertain');
    if any(unc_declarations)
        try
            diagnostic = solverobust(F(find(~unc_declarations)),h,options,recover(getvariables(sdpvar(F(find(unc_declarations))))));
            return
        catch
            if strfind(lasterr,'Undefined function ''solverobust'' ')
                display('***');
                display('It looks like you have failed to add yalmip/modules/robust to your path');
                display('Information on required paths https://yalmip.github.io/tutorial/installation/');
                display(['For complete path, use addpath(genpath(''' fileparts(which('yalmiptest.m')) '''))']);
                display('***');
                error(lasterr)
            else
                error(lasterr)
            end
        end
    end
end

if isequal(options.solver,'mpt') | nargin>=4
    solving_parametric = 1;
else
    solving_parametric = 0;
end

% Just for safety
if isempty(F) & isempty(logdetStruct)
    F = lmi;
end

if any(is(F,'sos'))
    error('You have SOS constraints. Perhaps you meant to call SOLVESOS.');
end

% Super stupido
if length(F) == 0 & isempty(h) & isempty(logdetStruct)
   diagnostic.yalmiptime = 0;
   diagnostic.solvertime = 0;
   diagnostic.info = 'No problems detected (YALMIP)';
   diagnostic.problem = 0;
   diagnostic.dimacs = [NaN NaN NaN NaN NaN NaN];
   return
end

% *************************************************************************
%% LOOK FOR AVAILABLE SOLVERS
% Finding solvers can be very slow on some systems. To alleviate this
% problem, YALMIP can cache the list of available solvers.
% *************************************************************************
if (options.cachesolvers==0) | isempty(CACHED_SOLVERS)
    getsolvertime = clock;
    solvers = getavailablesolvers(0,options);
    getsolvertime = etime(clock,getsolvertime);
    % CODE TO INFORM USERS ABOUT SLOW NETWORKS!
    if isempty(EXISTTIME)
        EXISTTIME = getsolvertime;
        NCHECKS = 1;
    else
        EXISTTIME = [EXISTTIME getsolvertime];
        NCHECKS = NCHECKS + 1;
    end
    if (options.cachesolvers==0)
        if ((NCHECKS >= 3 & (sum(EXISTTIME)/NCHECKS > 1)) | EXISTTIME(end)>2)
            if warningon
                info = 'Warning: YALMIP has detected that your drive or network is unusually slow.\nThis causes a severe delay in OPTIMIZE when I try to find available solvers.\nTo avoid this, use the options CACHESOLVERS in SDPSETTINGS.\nSee the FAQ for more information.\n';
                fprintf(info);
            end
        end
    end
    if length(EXISTTIME) > 5
        EXISTTIME = EXISTTIME(end-4:end);
        NCHECKS = 5;
    end
    CACHED_SOLVERS = solvers;
else
    solvers = CACHED_SOLVERS;
end

%here we are not actually selecting a solver, just checking whether it supports complex numbers
solverindex = min(find(strcmpi(lower({solvers.tag}),lower(options.solver))));
if isempty(solverindex)
	complexsolver = 0;
else
	solver = solvers(solverindex);
	complexsolver = solver.complex;
end

% Dualize the problem?
if ~isempty(F)
    if options.dualize == -1
        sdp = find(is(F,'sdp'));
        if ~isempty(sdp)
            if all(is(F(sdp),'sdpcone'))
                options.dualize = 1;
            end
        end
    end
end
if options.dualize == 1
    [Fd,objd,aux1,aux2,aux3,complexInfo] = dualize(F,h,[],[],[],options,complexsolver);
    options.dualize = 0;
    diagnostic = solvesdp(Fd,-objd,options);
    if ~isempty(complexInfo)
        for i = 1:length(complexInfo.replaced)
            n = size(complexInfo.replaced{i},1);
            re = 2*double(complexInfo.new{i}(1:n,1:n));
            im = 2*double(complexInfo.new{i}(1:n,n+1:end));
            im=triu((im-im')/2)-(triu((im-im')/2))';
            assign(complexInfo.replaced{i},re + sqrt(-1)*im);
        end
    end
    return
end

% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
% DID WE SELECT THE MOMENT SOLVER
% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if isequal(options.solver,'moment')
    if ~isempty(logdetStruct)
        error('Cannot dualize problems with logaritmic objective')
    end
    options.solver = options.moment.solver;
    [diagnostic,x,momentdata] = solvemoment(F,h,options,options.moment.order);
    diagnostic.momentdata = momentdata;
    diagnostic.xoptimal = x;
    return
end

% ******************************************
% COMPILE IN GENERALIZED YALMIP FORMAT
% ******************************************
[interfacedata,recoverdata,solver,diagnostic,F,Fremoved,ForiginalQuadratics] = compileinterfacedata(F,[],logdetStruct,h,options,0,solving_parametric,solvers);

% ******************************************
% FAILURE?
% ******************************************
if ~isempty(diagnostic)
    diagnostic.yalmiptime = etime(clock,yalmiptime);
    return
end

% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
% DID WE SELECT THE LMILAB SOLVER WITH A KYP
% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if  strcmpi(solver.tag,'lmilab') & any(is(F,'kyp'))
    [diagnostic,failed] = calllmilabstructure(F,h,options);
    if ~failed % Did this problem pass (otherwise solve using unstructured call)
        diagnostic.yalmiptime = etime(clock,yalmiptime)-diagnostic.solvertime;
        return
    end
end

% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
% DID WE SELECT THE KYPD SOLVER
% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if strcmpi(solver.tag,'kypd')
    diagnostic = callkypd(F,h,options);
    diagnostic.yalmiptime = etime(clock,yalmiptime)-diagnostic.solvertime;
    return
end

% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
% DID WE SELECT THE STRUL SOLVER
% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if strfind(solver.tag,'STRUL')
    diagnostic = callstrul(F,h,options);
    diagnostic.yalmiptime = etime(clock,yalmiptime)-diagnostic.solvertime;
    return
end

%******************************************
% DID WE SELECT THE MPT solver (backwards comb)
%******************************************
actually_save_output = interfacedata.options.savesolveroutput;
if strcmpi(solver.tag,'mpt') | strcmpi(solver.tag,'mpt-2') | strcmpi(solver.tag,'mpt-3') | strcmpi(solver.tag,'mpcvx') | strcmpi(solver.tag,'mplcp') | strcmpi(solver.tag,'pop')
    interfacedata.options.savesolveroutput = 1;
    if isempty(interfacedata.parametric_variables)
        if (nargin < 4 | ~isa(varargin{4},'sdpvar'))
            error('You must specify parametric variables.')
        else
            varargin{4} = reshape(varargin{4},[],1);
            interfacedata.parametric_variables = [];
            for i = 1:length(varargin{4})
                  interfacedata.parametric_variables = [interfacedata.parametric_variables;find(ismember(recoverdata.used_variables,getvariables(varargin{4}(i))))];
            end
            if isempty(varargin{5})
                interfacedata.requested_variables = [];
            else
                interfacedata.requested_variables = [];
                for i = 1:length(varargin{5})
                    interfacedata.requested_variables = [interfacedata.requested_variables;find(ismember(recoverdata.used_variables,getvariables(varargin{5}(i))))];
                end
            end
        end
    end
end

% *************************************************************************
% Just return the YALMIP model. Used when solving multiple objectives
% *************************************************************************
if isfield(options,'pureexport')
    interfacedata.recoverdata = recoverdata;
    diagnostic = interfacedata;
    return
end

if strcmpi(solver.version,'geometric') || (strcmpi(solver.tag,'bnb') && strcmpi(solver.lower.version,'geometric'))
    % Actual linear user variables
    if options.assertgpnonnegativity
        check = find(interfacedata.variabletype==0);
        check = setdiff(check,interfacedata.aux_variables);
        check = setdiff(check,interfacedata.evalVariables);
        check = setdiff(check,interfacedata.extended_variables);
        [lb,ub] = find_lp_bounds(interfacedata.F_struc,interfacedata.K);
        if ~all(lb(check)>=0)
            % User appears to have explictly selected a GP solver
            userdirect = ~isempty(strfind(options.solver,'geometric')) || ~isempty(strfind(options.solver,'mosek')) || ~isempty(strfind(options.solver,'gpposy'));
            userindirect = strcmpi(solver.tag,'bnb') && strcmpi(solver.lower.version,'geometric');
            if userdirect || userindirect
                % There are missing non-negativity bounds
                output = createOutputStructure(zeros(length(interfacedata.c),1)+NaN,[],[],18,yalmiperror(18,''),[],[],nan);
                diagnostic.yalmiptime = etime(clock,yalmiptime);
                diagnostic.solvertime = output.solvertime;
                try
                    diagnostic.info = output.infostr;
                catch
                    diagnostic.info = yalmiperror(output.problem,solver.tag);
                end
                diagnostic.problem = output.problem;
                if options.dimacs
                    diagnostic.dimacs = dimacs;
                end
                return
            else
                % YALMIP selected solver and picked a GP solver. As this is
                % no GP, we call again, but this time explicitly tell
                % YALMIP that it isn't a GP
                options.thisisnotagp = 1;
                varargin{3} = options;
                diagnostic = solvesdp(varargin{:});
                return
            end
        end
    end
end

% *************************************************************************
% TRY TO SOLVE PROBLEM
% *************************************************************************
if options.debug
    eval(['output = ' solver.call '(interfacedata);']);
else
    try
        eval(['output = ' solver.call '(interfacedata);']);
    catch
        output = createOutputStructure(zeros(length(interfacedata.c),1)+NaN,[],[],9,yalmiperror(9,lasterr),[],[],nan);
    end
end

if options.dimacs
    try
        b = -interfacedata.c;
        c = interfacedata.F_struc(:,1);
        A = -interfacedata.F_struc(:,2:end)';
        x = output.Dual;
        y = output.Primal;
        % FIX this nonlinear crap (return variable type in
        % compileinterfacedata)
        if options.relax == 0 & any(full(sum(interfacedata.monomtable,2)~=0))
            if ~isempty(find(sum(interfacedata.monomtable | interfacedata.monomtable,2)>1))
                z=real(exp(interfacedata.monomtable*log(y+eps)));
                y = z;
            end
        end

        if isfield(output,'Slack')
            s = output.Slack;
        else
            s = [];
        end

        dimacs = computedimacs(b,c,A,x,y,s,interfacedata.K);
    catch
        dimacs = [nan nan nan nan nan nan];
    end
else
    dimacs = [nan nan nan nan nan nan];
end

% ********************************
% ORIGINAL COORDINATES
% ********************************
output.Primal = recoverdata.x_equ+recoverdata.H*output.Primal;

% ********************************
% OUTPUT
% ********************************
diagnostic.yalmipversion = yalmip('ver');
diagnostic.matlabversion = version;
diagnostic.yalmiptime = etime(clock,yalmiptime)-output.solvertime;
diagnostic.solvertime = output.solvertime;
try
    diagnostic.info = output.infostr;
catch
    diagnostic.info = yalmiperror(output.problem,solver.tag);
end
diagnostic.problem = output.problem;
if options.dimacs
    diagnostic.dimacs = dimacs;
end

% Some more info is saved internally
solution_internal = diagnostic;
solution_internal.variables = recoverdata.used_variables(:);
solution_internal.optvar = output.Primal;

if ~isempty(interfacedata.parametric_variables)
    diagnostic.mpsol = output.solveroutput;
    options.savesolveroutput = actually_save_output;
end;

if interfacedata.options.savesolveroutput
    diagnostic.solveroutput = output.solveroutput;
end
if interfacedata.options.savesolverinput
    diagnostic.solverinput = output.solverinput;
end
if interfacedata.options.saveyalmipmodel
    diagnostic.yalmipmodel = interfacedata;
end

if options.warning & warningon & isempty(strfind(diagnostic.info,'No problems detected'))
    disp(['Warning: ' output.infostr]);
end

if ismember(output.problem,options.beeponproblem)
    try
        beep; % does not exist on all ML versions
    catch
    end
end

% And we are done! Save the result
if ~isempty(output.Primal)
    if size(output.Primal,2)>1
        for j = 1:size(output.Primal,2)
            temp = solution_internal;
            temp.optvar = temp.optvar(:,j);
            yalmip('setsolution',temp,j);
        end
    else
        yalmip('setsolution',solution_internal);
    end
end
if interfacedata.options.saveduals & solver.dual
    if isempty(interfacedata.Fremoved) | (nnz(interfacedata.Q)>0)
        try
            setduals(F,output.Dual,interfacedata.K);
        catch
        end
    else
        try
            % Duals related to equality constraints/free variables
            % have to be recovered b-A*x-Ht == 0
            b = -interfacedata.oldc;
            A = -interfacedata.oldF_struc(1+interfacedata.oldK.f:end,2:end)';
            H = -interfacedata.oldF_struc(1:interfacedata.oldK.f,2:end)';
            x = output.Dual;
            b_equ = b-A*x;
            newdual =  H\b_equ;
            setduals(interfacedata.Fremoved + F,[newdual;output.Dual],interfacedata.oldK);
        catch
             % this is a new feature...
            disp('Dual recovery failed. Please report this issue.');
        end
    end
end
% Hack to recover original QCQP duals from gurobi
if strcmp(solver.tag,'GUROBI-GUROBI')
    if length(ForiginalQuadratics) > 0
        if isfield(output,'qcDual')
            if length(output.qcDual) == length(ForiginalQuadratics)
             %   Ktemp.l = length(output.qcDual);
             %   Ktemp.f = 0;
             %   Ktemp.q = 0;
             %   Ktemp.s = 0;
             %   Ktemp.r = 0;
                Ftemp = F + ForiginalQuadratics;
                K = interfacedata.K;
                Ktemp = K;
                Ktemp.l = Ktemp.l + length(ForiginalQuadratics);
                tempdual = output.Dual;
                tempdual = [tempdual(1:K.f + K.l);-output.qcDual;tempdual(1+K.f+K.l:end)];
                setduals(Ftemp,tempdual,Ktemp);
%                setduals(ForiginalQuadratics,-output.qcDual,Ktemp);
            end
        end
    end
end

function yesno = warningon

s = warning;
yesno = isequal(s,'on');


%
% surf_registration_table.m
%
% Original Author: Laurence Wastiaux
% CVS Revision Info:
%    $Author: nicks $
%    $Date: 2011/03/02 00:04:13 $
%    $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
%

[Dsubj, nf, r90, thdemean, M] = surf_registration_stats('/space/neo/2/recon/buckner')
%load('/space/okapi/3/data/laurence/ADF/surf_registration/residual_var90.mat') %loads r90
%load('/space/okapi/3/data/laurence/ADF/surf_registration/Subj_Names.mat') %loads nf
%files=dir('/space/neo/2/recon/buckner');
fp=fopen('~/surfreg_table.txt', 'w');
fprintf(fp,'# FSAFD SurfRegistrationCheck 1\n# date 20050516\n# $Id: surf_registration_table.m,v 1.3 2011/03/02 00:04:13 nicks Exp $\n# Buckner data set\n# hemi lh\n# PercentRemovedVar 90\n# ncols 1\n# nrows %d\n# label_col 1 PercentResidualVariance\n', length(r90));
nn=1;
for i=1:length(r90)
    %nb=I(i);
    if(r90(i)>0)
        fprintf(fp, '# label_row %d %s\n', nn, char(nf(i).name));
        nn=nn+1;
    end

end
for j=1:length(r90)
    if(r90(j)>0)
        fprintf(fp, '%f\n', r90(j));
    end
end
fclose(fp)


function F = ctranspose(F)
% '   Conjugate transpose of a SPHEREFUNV.

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

F = transpose( F );
F = conj( F );

end


function areBadVals = AreBadValues(A)
% Only returns true for bad array elements.
% Bad array elements include Inf (infinity), NA (missing), and NaN (not a
% number).
%
%    usage: areBadVals = AreBadValues(A)

    areBadVals = ~isfinite(A);
    % Inf, NA, and NaN are non-finite values.

end


function [TABLE, beta, tstat] = ARDLprint(ARDL,vnames,approx,vnames_ex)
% =======================================================================
% Prints the output of a VAR estimation
% =======================================================================
% [beta, tstat, TABLE] = VARprint(VAR,VARopt,approx)
% -----------------------------------------------------------------------
% INPUT
%   - VAR: structure output of VARmodel function
%   - VARopt: options of the VAR (see VARopt from VARmodel)
% -----------------------------------------------------------------------
% OPTIONAL INPUT
%   approx: number of decimal digits. Default = 4
%------------------------------------------------------------------------
% OUPUT
%   beta: table of estimated coefficients in cell array
%   tstat: table of t-stats in cell array
%   TABLE: table of estimated coefficients and t-stats in cell array
% =======================================================================
% VAR Toolbox 3.0
% Ambrogio Cesa-Bianchi
% ambrogiocesabianchi@gmail.com
% March 2012. Updated November 2020
% -----------------------------------------------------------------------

%% Check inputs
%===============================================
% Check they are not empty
if isempty(vnames)
    error('You need to add label for endogenous variables in VARopt');
end
if ~exist('approx','var')
    approx = 4;
end
if ARDL.nvar_ex>0
    if ~exist('vnames_ex','var')
        error('You need to add label for exogenous variables');
    end
end

%% Retrieve and initialize variables
%=============================================================
nlag = ARDL.nlag;
nlag_ex = ARDL.nlag_ex;
const = ARDL.const;
% vnames_ex = vnames(2:end);
% vnames = vnames(1);

%% Additional checks
%=============================================================
% Check size of vnames (and change it if necessary)
htext = vnames;
nvars = 1;
nvars_ex = 1;

%% Labels of deterministic components
%===============================================
switch const
    case 0
        aux = [];
    case 1
        aux = {'c'};
    case 2
        aux = {'c';'trend'};
    case 3
        aux = {'c';'trend';'trend2'};
end
vtext = {' '};
vtext = [vtext; aux];
clear aux

%% Labels of lagged variables
%===============================================
for jj=1:nlag
    for ii=1:nvars
        aux(ii,1) = {[vnames{ii} '(-' num2str(jj) ')' ]};
    end
    vtext = [vtext ; aux];
end
clear aux

%% Labels of exogenous variables
%===============================================
vtext = [vtext ; vnames_ex'];
if nlag_ex > 0
    for jj=1:nlag_ex
        for ii=1:nvars_ex
            aux(ii,1) = {[vnames_ex{ii} '(-' num2str(jj) ')' ]};
        end
        vtext = [vtext ; aux];
    end
    clear aux
end

%% Save
%===============================================
% Save a beta table
beta = roundnum2cell(ARDL.beta,approx);
beta = [htext; beta];
beta = [vtext beta];

% Save a std err table
bstd = roundnum2cell(ARDL.bstd,approx);
bstd = [htext; bstd];
bstd = [vtext bstd];

% Save a tstat table
tstat = ARDL.tstat;
tstat = roundnum2cell(tstat,2);
tstat = [htext; tstat];
tstat = [vtext tstat];

% Save a p-value table
tprob = ARDL.tprob;
tprob = roundnum2cell(tprob,approx);
tprob = [htext; tprob];
tprob = [vtext tprob];

% Save a beta & tstat table
nn = size(beta,1)-1;
TABLE = {''};
index = 1;
for ii=1:nn
    for jj=1:nvars
        TABLE(index,jj) = beta(1+ii,1+jj);
        TABLE(index+1,jj) = bstd(1+ii,1+jj);
        aux1 = cell2mat(tstat(1+ii,1+jj)); % get the numeric value from cell
        aux2 = [ '[' num2str(aux1) ']' ];  % add parenthesis to t-stat value
        TABLE{index+2,jj} = aux2;
        TABLE(index+3,jj) = tprob(1+ii,1+jj);
    end
    index = index+4;
end
clear aux
TABLE = [htext; TABLE];

% Create vertical label
TAB_v = {''};
index = 2;
for ii=1:nn
    TAB_v(index,1) = vtext(1+ii);
    TAB_v(index+1,1) = {['std(' vtext{1+ii} ')']};
    TAB_v(index+2,1) = {['t(' vtext{1+ii} ')']};
    TAB_v(index+3,1) = {['p(' vtext{1+ii} ')']};
    index = index + 4;
end
TABLE = [TAB_v TABLE];
TABLE(index,2) = num2cell(ARDL.rsqr); TABLE(index,1) = {'R2'};    index = index+1;
TABLE(index,2) = num2cell(ARDL.rbar); TABLE(index,1) = {'R2bar'}; index = index+1;
if const>0
    TABLE(index,2) = num2cell(ARDL.F); TABLE(index,1) = {'F'};     index = index+1;
else
    TABLE(index,2) = [];               TABLE(index,1) = {'F'};     index = index+1;
end
TABLE(index,2) = num2cell(ARDL.nobs);  TABLE(index,1) = {'Obs'};   index = index+1;
%
% %% Print the table on screen (only beta)
% %===============================================
% info.cnames = char(htext);
% info.rnames = char(vtext);
% disp(' ')
% %disp('---------------------------------------------------------------------')
% disp(' ')
% disp('Reduced form VAR estimation:')
% disp(' ')
% mprint(ARDL.Ft,info)
% %disp('---------------------------------------------------------------------')


%TRPLOT Draw a coordinate frame
%
% TRPLOT(T, OPTIONS) draws a 3D coordinate frame represented by the homogeneous
% transform T (4x4).
%
% H = TRPLOT(T, OPTIONS) as above but returns a handle.
%
% TRPLOT(H, T) moves the coordinate frame described by the handle H to
% the pose T (4x4).
%
% TRPLOT(R, OPTIONS) as above but the coordinate frame is rotated about the
% origin according to the orthonormal rotation matrix R (3x3).
%
% H = TRPLOT(R, OPTIONS) as above but returns a handle.
%
% TRPLOT(H, R) moves the coordinate frame described by the handle H to
% the orientation R.
%
% Options::
% 'color',C          The color to draw the axes, MATLAB colorspec C
% 'noaxes'           Don't display axes on the plot
% 'axis',A           Set dimensions of the MATLAB axes to A=[xmin xmax ymin ymax zmin zmax]
% 'frame',F          The coordinate frame is named {F} and the subscript on the axis labels is F.
% 'text_opts', opt   A cell array of MATLAB text properties
% 'handle',H         Draw in the MATLAB axes specified by the axis handle H
% 'view',V           Set plot view parameters V=[az el] angles, or 'auto'
%                    for view toward origin of coordinate frame
% 'length',s         Length of the coordinate frame arms (default 1)
% 'arrow'            Use arrows rather than line segments for the axes
% 'width', w         Width of arrow tips (default 1)
% 'thick',t          Thickness of lines (default 0.5)
% '3d'               Plot in 3D using anaglyph graphics
% 'anaglyph',A       Specify anaglyph colors for '3d' as 2 characters for
%                    left and right (default colors 'rc'): chosen from
%                    r)ed, g)reen, b)lue, c)yan, m)agenta.
% 'dispar',D         Disparity for 3d display (default 0.1)
% 'text'             Enable display of X,Y,Z labels on the frame
% 'labels',L         Label the X,Y,Z axes with the 1st, 2nd, 3rd character of the string L
% 'rgb'              Display X,Y,Z axes in colors red, green, blue respectively
% 'rviz'             Display chunky rviz style axes
%
% Examples::
%
%       trplot(T, 'frame', 'A')
%       trplot(T, 'frame', 'A', 'color', 'b')
%       trplot(T1, 'frame', 'A', 'text_opts', {'FontSize', 10, 'FontWeight', 'bold'})
%       trplot(T1, 'labels', 'NOA');
%
%       h = trplot(T, 'frame', 'A', 'color', 'b');
%       trplot(h, T2);
%
% 3D anaglyph plot
%       trplot(T, '3d');
%
% Notes::
% - The 'rviz' option is equivalent to 'rgb', 'notext', 'noarrow',
%   'thick', 5.
% - The arrow option requires the third party package arrow3 from File
%   Exchange.
% - The handle H is an hgtransform object.
% - When using the form TRPLOT(H, ...) to animate a frame it is best to set
%   the axis bounds.
% - The '3d' option requires that the plot is viewed with anaglyph glasses.
% - You cannot specify 'color' and '3d' at the same time.
%
% See also TRPLOT2, TRANIMATE.

%TODO:
% 'rviz', chunky RGB lines, no arrows

% Copyright (C) 1993-2015, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

% TODO
%  need to decide how to handle scaling
%  what does hold on mean?  don't touch scaling?

function hout = trplot(T, varargin)

    if isscalar(T) && ishandle(T)
        % trplot(H, T)
        H = T; T = varargin{1};
        if isrot(T)
            T = r2t(T);
        end
        set(H, 'Matrix', T);

        % for the 3D case retrieve the right hgtransform and set it
        hg2 = get(H, 'UserData');
        if ~isempty(hg2)
            set(hg2, 'Matrix', T);
        end

        return;
    end

    if size(T,3) > 1
        error('trplot cannot operate on a sequence');
    end
    if ~ishomog(T) && ~isrot(T)
        error('trplot operates only on transform (4x4) or rotation matrix (3x3)');
    end

    opt.color = [];
    opt.rgb = false;
    opt.axes = true;
    opt.axis = [];
    opt.frame = [];
    opt.text_opts = [];
    opt.view = [];
    opt.width = 1;
    opt.arrow = false;
    opt.labels = 'XYZ';
    opt.handle = [];
    opt.anaglyph = 'rc';
    opt.d_3d = false;
    opt.dispar = 0.1;
    opt.thick = 0.5;
    opt.length = 1;
    opt.text = true;
    opt.lefty = false;
    opt.rviz = false;

    opt = tb_optparse(opt, varargin);

    if opt.rviz
        opt.thick = 5;
        opt.arrow = false;
        opt.rgb = true;
        opt.text = false;
    end

    if ~isempty(opt.color) && opt.d_3d
        error('cannot specify ''color'' and ''3d'', use ''anaglyph'' option');
    end
    if isempty(opt.color)
        opt.color = 'b';
    end
    if isempty(opt.text_opts)
        opt.text_opts = {};
    end

    if opt.d_3d
        opt.color = ag_color(opt.anaglyph(1));
    end

    if isempty(opt.axis)
        % determine some default axis dimensions

        % get the origin of the frame
        if isrot(T)
            c = [0 0 0];  % at zero for a rotation matrix
        else
            c = transl(T);
        end

        d = 1.2;
        opt.axis = [c(1)-d c(1)+d c(2)-d c(2)+d c(3)-d c(3)+d];

    end

    % TODO: should do the 2D case as well

    if ~isempty(opt.handle)
        hax = opt.handle;
        hold(hax);
    else
        ih = ishold;
        if ~ih
            % if hold is not on, then clear the axes and set scaling
            cla
            if ~isempty(opt.axis)
                axis(opt.axis);
            end
            daspect([1 1 1]);

            if opt.axes
                xlabel( 'X');
                ylabel( 'Y');
                zlabel( 'Z');
                rotate3d on
            end
            new_plot = true;
        end
        hax = gca;
        hold on
    end
    % hax is the handle for the axis we will work with, either new or
    % passed by option 'handle'

    opt.text_opts = [opt.text_opts, 'Color', opt.color];

    hg = hgtransform('Parent', hax);

    % trplot( Q.R, fmt, color);
    if isrot(T)
        T = r2t(T);
    end

    % create unit vectors
    o =  [0 0 0]';
    x1 = opt.length*[1 0 0]';
    y1 = opt.length*[0 1 0]';
    if opt.lefty
        z1 = opt.length*[0 0 -1]';
    else
        z1 = opt.length*[0 0 1]';
    end

    % draw the axes

    mstart = [o o o]';
    mend = [x1 y1 z1]';

    if opt.rgb
        axcolors = {'r', 'g', 'b'};
    else
        axcolors = { opt.color, opt.color, opt.color};
    end

    if opt.arrow
%         % draw the 3 arrows
%         S = [opt.color num2str(opt.width)];
%         ha = arrow3(mstart, mend, S);
%         for h=ha'
%             set(h, 'Parent', hg);
%         end
          daspect([1,1,1])
          for i=1:3
              ha = arrow3(mstart(i,1:3), mend(i,1:3), [axcolors{i} num2str(opt.width)]);
              set(ha, 'Parent', hg);
          end
    else
        for i=1:3
            plot2([mstart(i,1:3); mend(i,1:3)], 'Color', axcolors{i}, ...
                'LineWidth', opt.thick, ...
                'Parent', hg);
        end
    end

    % label the axes
    if isempty(opt.frame)
        fmt = '%c';
    else
        fmt = sprintf('%%c_{%s}', opt.frame);
    end

    if opt.text
        % add the labels to each axis
        h = text(x1(1), x1(2), x1(3), sprintf(fmt, opt.labels(1)), 'Parent', hg);
        set(h, opt.text_opts{:});

        h = text(y1(1), y1(2), y1(3), sprintf(fmt, opt.labels(2)), 'Parent', hg);
        set(h, opt.text_opts{:});

        h = text(z1(1), z1(2), z1(3), sprintf(fmt, opt.labels(3)), 'Parent', hg);
        set(h, opt.text_opts{:});
    end

    % label the frame
    if ~isempty(opt.frame)
        h = text(o(1)-0.04*x1(1), o(2)-0.04*y1(2), o(3)-0.04*z1(3), ...
            ['\{' opt.frame '\}'], 'Parent', hg);
        set(h, 'VerticalAlignment', 'middle', ...
            'HorizontalAlignment', 'center', opt.text_opts{:});
    end

    if ~opt.axes
        set(gca, 'visible', 'off');
    end
    if ischar(opt.view) && strcmp(opt.view, 'auto')
        cam = x1+y1+z1;
        view(cam(1:3));
    elseif ~isempty(opt.view)
        view(opt.view);
    end
    if isempty(opt.handle) && ~ih
        grid on
        hold off
    end

    % now place the frame in the desired pose
    set(hg, 'Matrix', T);

    if opt.d_3d
        % 3D display.  The original axes are for the left eye, and we add
        % another set of axes to the figure for the right eye view and
        % displace its camera to the right of that of that for the left eye.
        % Then we recursively call trplot() to create the right eye view.

        left = gca;
        right = axes;

        % compute the offset in world coordinates
        off = -t2r(view(left))'*[opt.dispar 0 0]';
        pos = get(left, 'CameraPosition');

        set(right, 'CameraPosition', pos+off');
        set(right, 'CameraViewAngle', get(left, 'CameraViewAngle'));
        set(right, 'CameraUpVector', get(left, 'CameraUpVector'));
        target = get(left, 'CameraTarget');
        set(right, 'CameraTarget', target+off');

        % set perspective projections
                set(left, 'Projection', 'perspective');
        set(right, 'Projection', 'perspective');

        % turn off axes for right view
        set(right, 'Visible', 'Off');

        % set color for right view
        hg2 = trplot(T, 'color', ag_color(opt.anaglyph(2)));

        % the hgtransform for the right view is user data for the left
        % view hgtransform, we need to change both when we rotate the
        % frame.
        set(hg, 'UserData', hg2);
    end

    % optionally return the handle, for later modification of pose
    if nargout > 0
        hout = hg;
    end
end

function out = ag_color(c)

% map color character to an color triple, same as anaglyph.m

    % map single letter color codes to image planes
    switch c
    case 'r'
        out = [1 0 0];        % red
    case 'g'
        out = [0 1 0];        % green
    case 'b'
        % blue
        out = [0 0 1];
    case 'c'
        out = [0 1 1];        % cyan
    case 'm'
        out = [1 0 1];        % magenta
    case 'o'
        out = [1 1 0];        % orange
    end
end


function [ux, vx, wx] = spm_fx_cmc_tfm_gen(x,u,P,M,option)
% Generate pre synaptic signals for multimodal DCM for fMRI and M/EEG
% FORMAT [u,v,w]  = spm_fx_cmc_tfm_gen(x,u,P,M)
% FORMAT [u,v]    = spm_fx_cmc_tfm_gen(x,u,P,M)
% FORMAT [u]      = spm_fx_cmc_tfm_gen(x,u,P,M)
%
% Inputs:
% -------------------------------------------------------------------------
% x      - state vector
%   x(:,1) - voltage     (spiny stellate cells)
%   x(:,2) - conductance (spiny stellate cells)
%   x(:,3) - voltage     (superficial pyramidal cells)
%   x(:,4) - conductance (superficial pyramidal cells)
%   x(:,5) - current     (inhibitory interneurons)
%   x(:,6) - conductance (inhibitory interneurons)
%   x(:,7) - voltage     (deep pyramidal cells)
%   x(:,8) - conductance (deep pyramidal cells)
% P        - parameters of canonical micro circuits
% u        - exogenous input
% M        - neural-mass model structure
% option   - options array for calculation pre synaptic signals {1 x 4}:
%   option{1} - 'pre' (pre synaptic) or 'de' (decomposed into intrinsic
%               inhibitory, intrinsic excitatory and extrinsic excitatory)
%               NVC drive.
%   option{2} - 'd' (different) or 's' (same) parameters of neurovascular
%               scaling (this option is not used within this function).
%   option{3} - 'int' (only intrinsic neuronal signals are taken to account
%               for simulating presynaptic signals) or 'ext' (external
%               neuronal signals are additional included).
%   option{4} - EX, a 4x1 matrix  with either 0 or 1 elements (order as
%               follows: [x(:,1) x(:,3) x(:,5) x(:,7)]) to exclude or
%               include populations from calculation of pre synaptic signal
%
%  Examples of options               {'pre',   'd',    'int', EX},
%                                    {'pre',   's',    'int', EX},
%                                    {'pre',   'd',    'ext', EX},
%                                    {'pre',   's',    'ext', EX},
%                                    {'de',    's',    'int', EX},
%                                    {'de',    's',    'ext', EX},
%                                    {'de',    'd',    'int', EX},
%                                    {'de',    'd',    'ext', EX},
%
% Outputs:
% -------------------------------------------------------------------------
%  ux = spm_fx_cmc_tfm(x,u,P,M,option)
%  ux  -  simulated presynaptic signal (including or exclude distal regions)
%
% [ux,vx] = spm_fx_cmc_tfm_gen(x,u,P,M,option)
% ux  - intrinsic presynaptic input, (inhibitory)-without external input
% vx  - intrinsic presynaptic input (excitatory)-without external input
%
% [ux,vx,wx] = spm_fx_cmc_tfm_gen(x,u,P,M,,option)
% ux  - intrinsic presynaptic input, (inhibitory)
% vx  - intrinsic presynaptic input (excitatory)
% wx  - extrinsic presynaptic input
%--------------------------------------------------------------------------
% Prior fixed parameter scaling [Defaults]
%
% E  = (forward and backward) extrinsic rates
% G  = intrinsic rates
% D  = propagation delays (intrinsic, extrinsic)
% T  = synaptic time constants
% R  = slope of sigmoid activation function
%
%__________________________________________________________________________
% David O, Friston KJ (2003) A neural mass model for MEG/EEG: coupling and
% neuronal dynamics. NeuroImage 20: 1743-1755
%__________________________________________________________________________
% Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging

% Amirhossein Jafarian, and Karl Friston
% $Id: spm_fx_cmc_tfm_gen.m 7735 2019-12-02 09:15:27Z peter $

persistent in1 in2 in3 ;

% get dimensions and configure state variables
%--------------------------------------------------------------------------
x  = spm_unvec(x,M.x);                % neuronal states
n  = size(x,1);                       % number of sources

% [default] fixed parameters
%--------------------------------------------------------------------------
E  = [2 1 1 1]*512;                   % extrinsic (forward and backward)
T  = [16 8 1 2]*16;                   % synaptic rate constants
R  = 1;                               % gain of activation function
B  = 0;                               % baseline firing

% Extrinsic connections
%--------------------------------------------------------------------------
% ss = spiny stellate
% sp = superficial pyramidal
% dp = deep pyramidal
% ii = inhibitory interneurons
%--------------------------------------------------------------------------
A{1} = exp(P.A{1})*E(1);              % forward  connections (sp -> ss)
A{2} = exp(P.A{2})*E(2);              % forward  connections (sp -> dp)
A{3} = exp(P.A{3})*E(3);              % backward connections (dp -> sp)
A{4} = exp(P.A{4})*E(4);              % backward connections (dp -> ii)

% input connections
%--------------------------------------------------------------------------
C    = exp(P.C);

% pre-synaptic inputs: s(V)
%--------------------------------------------------------------------------
ig   = 2*(1:4);                       % indices of conductance
iv   = ig - 1;                        % indices of voltage
V    = x(:,iv);                       % Voltage
F    = 1./(1 + exp(B - R*V));         % firing rate
S    = F - 1/(1 + exp(B));            % deviation

% input
%==========================================================================
if isfield(M,'u')

    % endogenous input
    %----------------------------------------------------------------------
    U   = u(:)*128;
    M.m = size(U,1);

else
    % exogenous input
    %----------------------------------------------------------------------
    U   = C*u(:)*2;
    M.m = size(C,2);

end
clear u

% time constants and intrinsic connections
%==========================================================================
T      = ones(n,1)*T;
i      = 1:size(P.T,2);
T(:,i) = T(:,i).*exp(P.T);

% extrinsic connections
%--------------------------------------------------------------------------
% forward  A{1}  sp -> ss
% forward  A{2}  sp -> dp
% backward A{3}  dp -> sp
% backward A{4}  dp -> ii
%--------------------------------------------------------------------------

% Neuronal states (deviations from baseline)
%--------------------------------------------------------------------------
%   x(:,1) - voltage     (spiny stellate cells)
%   x(:,2) - conductance (spiny stellate cells)but
%   x(:,3) - voltage     (superficial pyramidal cells)
%   x(:,4) - conductance (superficial pyramidal cells)
%   x(:,5) - current     (inhibitory interneurons)
%   x(:,6) - conductance (inhibitory interneurons)
%   x(:,7) - voltage     (deep pyramidal cells)
%   x(:,8) - conductance (deep pyramidal cells)
%--------------------------------------------------------------------------
%     ss sp ii dp   % intrinsic connections
%--------------------------------------------------------------------------
g  = [-8 -4  -4  0;  % ss
       4 -8  -2  0;  % sp
       4  2  -4 -2;  % ii
       0  1  -2 -4]; % dp

g  = g*256*exp(P.S);

% intrinsic connections to be optimised (only the first is modulated)
%--------------------------------------------------------------------------
G       = ones(n,1)*diag(g)';
i       = 1:size(P.G,2);
G(:,i)  = G(:,i).*exp(P.G);

% Modulatory effects of sp depolarisation on recurrent inhibition
%--------------------------------------------------------------------------
if isfield(P,'M')
    G(:,2) = G(:,2).*exp(-P.M*32*S(:,2));
end

% Motion of states: f(x)
%--------------------------------------------------------------------------
% Afferents
%==========================================================================
u      = zeros(n,4);                % intrinsic - inhibitory
v      = zeros(n,4);                % intrinsic - excitatory
w      = zeros(n,4);                % extrinsic - excitatory
pre_ext    = zeros(n,4);            % pre-synaptics with extrinsic input
pre_no_ext = zeros(n,4);            % pre-synaptics without extrinsic input
pincluded  = option{4};             % included populations (binary vector)

% Granular layer (excitatory interneurons): spiny stellate: Hidden causes
%--------------------------------------------------------------------------
u(:,1) = G(:,1).*S(:,1) + g(1,3)*S(:,3) + g(1,2)*S(:,2);
w(:,1) = A{1}*S(:,2) + U;
pre_no_ext(:,1) = u(:,1);
pre_ext(:,1)    = u(:,1) + w(:,1);

% Supra-granular layer (superficial pyramidal cells): Hidden causes - error
%--------------------------------------------------------------------------
u(:,2) = G(:,2).*S(:,2) + g(2,3)*S(:,3);
v(:,2) = g(2,1)*S(:,1);
w(:,2) = A{3}*S(:,4);
pre_no_ext(:,2) = u(:,2) + v(:,2);
pre_ext(:,2)    = u(:,2) + v(:,2) + w(:,2);

% Supra-granular layer (inhibitory interneurons): Hidden states - error
%--------------------------------------------------------------------------
u(:,3) = G(:,3).*S(:,3);
v(:,3) = g(3,1)*S(:,1) + g(3,4)*S(:,4) + g(3,2)*S(:,2);
w(:,3) = A{4}*S(:,4);
pre_no_ext(:,3) = u(:,3) + v(:,3);
pre_ext(:,3)    = u(:,3) + v(:,3) + w(:,3);

% Infra-granular layer (deep pyramidal cells): Hidden states
%--------------------------------------------------------------------------
u(:,4) = G(:,4).*S(:,4) + g(4,3)*S(:,3);
v(:,4) = g(4,2)*S(:,2);
w(:,4) = A{2}*S(:,2);
pre_no_ext(:,4) = u(:,4) + v(:,4);
pre_ext(:,4)    = u(:,4) + v(:,4) + w(:,4);

% Switch off unused connections
%--------------------------------------------------------------------------
u(:,~pincluded)=0;
v(:,~pincluded)=0;
w(:,~pincluded)=0;
pre_ext(:,~pincluded)=0;
pre_no_ext(:,~pincluded)=0;

% output
%--------------------------------------------------------------------------
t = 1 ;
if (strcmp(option{3}, 'ext')&& strcmp(option{1}, 'pre'))
    in1(:,:,t)  = pre_ext;
    ux(:,:,t)    = in1;
end
if(strcmp(option{3}, 'int') && strcmp(option{1}, 'pre'))
    in1(:,:,t)  = pre_no_ext;
    ux(:,:,t)    = in1;
end
if(strcmp(option{1}, 'de'))
    in1(:,:,t)  = u ;
    in2(:,:,t)  = v;
    in3(:,:,t)  = w;
    ux(:,:,t)  = in1;
    vx(:,:,t)  = in2;
    wx(:,:,t)  = in3;
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%	Implemetation of the tracker described in paper
%	"MEEM: Robust Tracking via Multiple Experts using Entropy Minimization",
%   Jianming Zhang, Shugao Ma, Stan Sclaroff, ECCV, 2014
%
%	Copyright (C) 2014 Jianming Zhang
%
%	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/>.
%
%	If you have problems about this software, please contact: jmzhang@bu.edu
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function config = makeConfig(frame,selected_rect,use_color,use_experts,use_iif, show_img)
warning('off','MATLAB:maxNumCompThreads:Deprecated');
maxNumCompThreads(1);% The rounding error due to using differen number of threads
                     % could cause different tracking results.  On most sequences,
                     % the difference is very small, while on some challenging
                     % sequences, the difference can be substantial due to
                     % "butterfly effects". Therefore, we suggest using
                     % Spatial Robustness Evaluation (SRE) to benchmark
                     % trackers.
if nargin < 5
    use_iif = true;
end

%% default setting up

config.search_roi = 2; % ratio of the search roi to tracking window
config.padding = 40; % for object out of border

config.debug = false;
config.verbose = false;
config.display = show_img; % show tracking result at runtime
config.use_experts = use_experts;
config.use_raw_feat = false; % raw intensity feature value
config.use_iif = use_iif; % use illumination invariant feature

config.svm_thresh = -0.7; % for detecting the tracking failure
config.max_expert_sz = 4;
config.expert_update_interval = 50;
config.update_count_thresh = 1;
config.entropy_score_winsize = 5;
config.expert_lambda = 10;
config.label_prior_sigma = 15;

config.hist_nbin = 32; % histogram bins for iif computation

config.thresh_p = 0.1; % IOU threshold for positive training samples
config.thresh_n = 0.5; % IOU threshold for negative ones

%%
%  automatic setting up for determining grid sample step and feature channels
%  (do not change the following)

% check if the frame is in RGB format
config.use_color = false;
if (size(frame,3) == 3 && ~isequal(frame(:,:,1),frame(:,:,2),frame(:,:,3))) && use_color
    config.use_color = true;
end

% decide feature channel number
if config.use_color
    thr_n = 5;
else
    thr_n = 9;
end
config.thr = (1/thr_n:1/thr_n:1-1/thr_n)*255;
config.fd = numel(config.thr);

% decide image scale and pixel step for sampling feature
% rescale raw input frames propoerly would save much computation
frame_min_width = 320;
trackwin_max_dimension = 64;
template_max_numel = 144;
frame_sz = size(frame);

if max(selected_rect(3:4)) <= trackwin_max_dimension ||...
        frame_sz(2) <= frame_min_width
    config.image_scale = 1;
else
    min_scale = frame_min_width/frame_sz(2);
    config.image_scale = max(trackwin_max_dimension/max(selected_rect(3:4)),min_scale);
end
wh_rescale = selected_rect(3:4)*config.image_scale;
win_area = prod(wh_rescale);
config.ratio = (sqrt(template_max_numel/win_area));
template_sz = round(wh_rescale*config.ratio);
config.template_sz = template_sz([2 1]);


function varargout = spm_SpUtil(varargin)
% Space matrix utilities
% FORMAT varargout = spm_SpUtil(action,varargin)
%
%_______________________________________________________________________
%
% spm_SpUtil is a multi-function function containing various utilities
% for Design matrix and contrast construction and manipulation. In
% general, it accepts design matrices as plain matrices or as space
% structures setup by spm_sp.
%
% Many of the space utilities are computed using an SVD of the design
% matrix. The advantage of using space structures is that the svd of
% the design matrix is stored in the space structure, thereby saving
% unnecessary repeated computation of the SVD. This presents a
% considerable efficiency gain for large design matrices.
%
% Note that when space structures are passed as arguments is is
% assummed that their basic fields are filled in. See spm_sp for
% details of (design) space structures and their manipulation.
%
% Quick Reference    :
%---------------------
% ('isCon',x,c)      :
% ('allCon',x,c)     :
% ('ConR',x,c)       :
% ('ConO',x,c)       :
% ('size',x,dim)     :
% ('iX0check',i0,sL) :
%---------------------
% ('i0->c',x,i0)     : Out : c
% ('c->Tsp',x,c)     : Out : [X1o [X0]]
% ('+c->Tsp',x,c)    : Out : [ukX1o [ukX0]]
% ('i0->x1o',x,i0)   : Use ('i0->c',x,i0) and ('c->Tsp',X,c)
% ('+i0->x1o',x,i0)  : Use ('i0->c',x,i0) and ('+c->Tsp',X,c)
% ('X0->c',x,X0)     :~
% ('+X0->c',x,cukX0) :~
%---------------------
% ('trRV',x[,V])     :
% ('trMV',x[,V])     :
% ('i0->edf',x,i0,V) :
%
%---------------------
%
% Improvement compared to the spm99 beta version :
%
% Improvements in df computation using spm_SpUtil('trRV',x[,V]) and
% spm_SpUtil('trMV',sX [,V]). The degrees of freedom computation requires
% in general that the trace of RV and of RVRV be computed, where R is a
% projector onto either a sub space of the design space or the residual
% space, namely the space that is orthogonal to the design space. V is
% the (estimated or assumed) variance covariance matrix and is a number
% of scans by number of scans matrix which can be huge in some cases. We
% have (thanks to S Rouquette and JB) speed up this computation
% by using matlab built in functions of the frobenius norm and some theorems
% on trace computations.
%
% ======================================================================
%
% FORMAT i = spm_SpUtil('isCon',x,c)
% Tests whether weight vectors specify contrasts
% x   - Design matrix X, or space structure of X
% c   - contrast matrix (I.e. matrix of contrast weights, contrasts in columns)
%       Must have column dimension matching that of X
%       [defaults to eye(size(X,2)) to test uniqueness of parameter estimates]
% i   - logical row vector indiciating estimability of contrasts in c
%
% A linear combination of the parameter estimates is a contrast if and
% only if the weight vector is in the space spanned by the rows of X.
%
% The algorithm works by regressing the contrast weight vectors using
% design matrix X' (X transposed). Any contrast weight vectors will be
% fitted exactly by this procedure, leaving zero residual. Parameter
% tol is the tolerance applied when searching for zero residuals.
%
% Christensen R (1996)
%   "Plane Answers to Complex Questions"
%    2nd Ed. Springer-Verlag, New York
%
% Andrade A, Paradis AL, Rouquette S and Poline JB, NeuroImage 9, 1999
%                           ----------------
%
% FORMAT i = spm_SpUtil('allCon',x,c)
% Tests whether all weight vectors specify contrasts:
% Same as all(spm_SpUtil('isCon',x,c)).
%
%                           ----------------
%
% FORMAT r = spm_SpUtil('ConR',x,c)
% Assess orthogonality of contrasts (wirit the data)
% x   - Design matrix X, or space structure of X
% c   - contrast matrix (I.e. matrix of contrast weights, contrasts in columns)
%       Must have column dimension matching that of X
%       defaults to eye(size(X,2)) to test independence of parameter estimates
% r   - Contrast correlation matrix, of dimension the number of contrasts.
%
% For the general linear model Y = X*B + E, a contrast weight vector c
% defines a contrast c*B. This is estimated by c*b, where b are the
% least squares estimates of B given by b=pinv(X)*Y. Thus, c*b = w*Y,
% where weight vector w is given by w=c*pinv(X); Since the data are
% assummed independent, two contrasts are indpendent if the
% corresponding weight vectors are orthogonal.
%
% r is the matrix of normalised inner products between the weight
% vectors corresponding to the contrasts. For iid E, r is the
% correlation matrix of the contrasts.
%
% The logical matrix ~r will be true for orthogonal pairs of contrasts.
%
%                           ----------------
%
% FORMAT r = spm_SpUtil('ConO',x,c)
% Assess orthogonality of contrasts (wirit the data)
% x   - Design matrix X, or space structure of X
% c   - contrast matrix (I.e. matrix of contrast weights, contrasts in columns)
%       Must have column dimension matching that of X
%       [defaults to eye(size(X,2)) to test uniqueness of parameter estimates]
% r   - Contrast orthogonality matrix, of dimension the number of contrasts.
%
% This is the same as ~spm_SpUtil('ConR',X,c), but uses a quicker
% algorithm by looking at the orthogonality of the subspaces of the
% design space which are implied by the contrasts:
%       r = abs(c*X'*X*c')<tol
%
%                           ----------------
%
% FORMAT c = spm_SpUtil('i0->c',x,i0)
% Return F-contrast for specified design matrix partition
% x   - Design matrix X, or space structure of X
% i0  - column indices of null hypothesis design matrix
%
% This functionality returns a rank n mxp matrix of contrasts suitable
% for an extra-sum-of-squares F-test comparing the design X, with a
% reduced design. The design matrix for the reduced design is X0 =
% X(:,i0), a reduction of n degrees of freedom.
%
% The algorithm, due to J-B, and derived from Christensen, computes the
% contrasts as an orthonormal basis set for the rows of the
% hypothesised redundant columns of the design matrix, after
% orthogonalisation with respect to X0. For non-unique designs, there
% are a variety of ways to produce equivalent F-contrasts. This method
% produces contrasts with non-zero weights only for the hypothesised
% redundant columns.
%
%                           ----------------
%
% case {'x0->c'}                %-
% FORMAT c = spm_SpUtil('X0->c',sX,X0)
%                           ----------------
%
% FORMAT [X1,X0] = spm_SpUtil('c->TSp',X,c)
% Orthogonalised partitioning of design space implied by F-contrast
% x   - Design matrix X, or space structure of X
% c   - contrast matrix (I.e. matrix of contrast weights, contrasts in columns)
%       Must have column dimension matching that of X
% X1o - contrast space - design matrix corresponding according to contrast
%       (orthogonalised wirit X0)
% X0  - matrix reduced according to null hypothesis
%       (of same size as X but rank deficient)
% FORMAT [uX1,uX0] = spm_SpUtil('c->TSp+',X,c)
%        + version to deal with the X1o and X0 partitions in the "uk basis"
%
% ( Note that unless X0 is reduced to a set of linearely independant   )
% ( vectors, c will only be contained in the null space of X0.  If X0  )
% ( is "reduced", then the "parent" space of c must be reduced as well )
% ( for c to be the actual null space of X0.                           )
%
% This functionality returns a design matrix subpartition whose columns
% span the hypothesised null design space of a given contrast. Note
% that X1 is orthogonal(ised) to X0, reflecting the situation when an
% F-contrast is tested using the extra sum-of-squares principle (when
% the extra distance in the hypothesised null space is measured
% orthogonal to the space of X0).
%
% Note that the null space design matrix will probably not be a simple
% sub-partition of the full design matrix, although the space spanned
% will be the same.
%
%                           ----------------
%
% FORMAT X1 = spm_SpUtil('i0->x1o',X,i0)
% x   - Design matrix X, or space structure of X
% i0  - Columns of X that make up X0 - the reduced model (Ho:B1=0)
% X1  - Hypothesised null design space, i.e. that part of X orthogonal to X0
% This offers the same functionality as the 'c->TSp' option, but for
% simple reduced models formed from the columns of X.
%
% FORMAT X1 = spm_SpUtil('i0->x1o+',X,i0)
%        + version to deal with the X1o and X0 partitions in the "uk basis"
%
%                           ----------------
%
% FORMAT [trRV,trRVRV] = spm_SpUtil('trRV',x[,V])
% trace(RV) & trace(RVRV) - used in df calculation
% x      - Design matrix X, or space structure of X
% V      - V matrix [defult eye] (trRV == trRVRV if V==eye, since R idempotent)
% trRV   - trace(R*V),     computed efficiently
% trRVRV - trace(R*V*R*V), computed efficiently
% This uses the Karl's cunning understanding of the trace:
%              (tr(A*B) = sum(sum(A'*B)).
% If the space of X is set, then algorithm uses x.u to avoid extra computation.
%
%                           ----------------
%
% FORMAT [trMV, trMVMV]] = spm_SpUtil('trMV',x[,V])
% trace(MV) & trace(MVMV) if two ouput arguments.
% x      - Design matrix X, or space structure of X
% V      - V matrix [defult eye] (trMV == trMVMV if V==eye, since M idempotent)
% trMV   - trace(M*V),     computed efficiently
% trMVMV - trace(M*V*M*V), computed efficiently
% Again, this uses the Karl's cunning understanding of the trace:
%              (tr(A*B) = sum(sum(A'.*B)).
% If the space of X is set, then algorithm uses x.u to avoid extra computation.
%
%                           ----------------
%
% OBSOLETE use FcUtil('H') for spm_SpUtil('c->H',x,c)
% Extra sum of squares matrix O for beta's from contrast
% x   - Design matrix X, or space structure of X
% c   - contrast matrix (I.e. matrix of contrast weights, contrasts in columns)
%       Must have column dimension matching that of X
% O   - Matrix such that b'*O*b = extra sum of squares for F-test of contrast c
%
%                           ----------------
%
% OBSOLETE use spm_sp('=='...) for spm_SpUtil('c==X1o',x,c) {or 'cxpequi'}
% x   - Design matrix X, or space structure of X
% c   - contrast matrix (I.e. matrix of contrast weights, contrasts in columns)
%       Must have column dimension matching that of X
% b   - True is c is a spanning set for space of X
%       (I.e. if contrast and space test the same thing)
%
%                           ----------------
%
% FORMAT [df1,df2] = spm_SpUtil('i0->edf',x,i0,V) {or 'edf'}
% (effective) df1 and df2 the residual df for the projector onto the
% null space of x' (residual forming projector) and the numerator of
% the F-test where i0 are the columns for the null hypothesis model.
% x   - Design matrix X, or space structure of X
% i0  - Columns of X corresponding to X0 partition X = [X1,X0] & with
%       parameters B = [B1;B0]. Ho:B1=0
% V   - V matrix
%
%                           ----------------
%
% FORMAT  sz           = spm_SpUtil('size',x,dim)
% FORMAT [sz1,sz2,...] = spm_SpUtil('size',x)
% Returns size of design matrix
% (Like MatLab's `size`, but copes with design matrices inside structures.)
% x   - Design matrix X, or structure containing design matrix in field X
%       (Structure needn't be a space structure.)
% dim - dimension which to size
% sz  - size
%
%_______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Andrew Holmes Jean-Baptiste Poline
% $Id: spm_SpUtil.m 4137 2010-12-15 17:18:32Z guillaume $

% (frobenius norm trick by S. Rouquette)

%-Format arguments
%-----------------------------------------------------------------------
if nargin==0, error('do what? no arguments given...')
else action = varargin{1}; end

switch lower(action),

case {'iscon','allcon','conr','cono'}
%=======================================================================
% i = spm_SpUtil('isCon',x,c)
if nargin==0, varargout={[]}; error('isCon : no argument specified'), end;
if nargin==1,
   varargout={[]}; warning('isCon : no contrast specified'); return;
end;
if ~spm_sp('isspc',varargin{2})
     sX = spm_sp('Set',varargin{2});
else sX = varargin{2}; end
if nargin==2, c=eye(spm_sp('size',sX,2)); else c=varargin{3}; end;
if isempty(c), varargout={[]}; return, end

switch lower(action)
    case 'iscon'
        varargout = { spm_sp('eachinspp',sX,c) };
    case 'allcon'
        varargout = {spm_sp('isinspp',sX,c)};
    case 'conr'
        if size(c,1) ~= spm_sp('size',sX,2)
            error('Contrast not of the right size'), end
        %-Compute inner products of data weight vectors
        % (c'b = c'*pinv(X)*Y = w'*Y
        % (=> w*w' = c'*pinv(X)*pinv(X)'*c == c'*pinv(X'*X)*c
        r   = c'*spm_sp('XpX-',sX)*c;
        %-normalize by "cov(r)" to get correlations
        r   = r./(sqrt(diag(r))*sqrt(diag(r))');
        r(abs(r) < sX.tol)=0;       %-set near-zeros to zero
        varargout = {r};                %-return r
    case 'cono'
        %-This is the same as ~spm_SpUtil('ConR',x,c), and so returns
        % the contrast orthogonality (though not their corelations).
        varargout = { abs(c'* spm_sp('XpX',sX) *c) < sX.tol};
end

case {'+c->tsp','c->tsp'}    %- Ortho. partitioning implied by F-contrast
%=======================================================================
% spm_SpUtil('c->Tsp',sX,c)
% + version of 'c->tsp'.
% The + version returns the same in the base u(:,1:r).

%--------- begin argument check ------------------------------
if nargin ~= 3, error(['Wrong number of arguments in ' action])
else sX = varargin{2}; c = varargin{3}; end;
if nargout > 2, error(['Too many output arguments in ' action]), end;
if ~spm_sp('isspc',sX),  sX = spm_sp('set',varargin{2}); end;
if sX.rk == 0, error('c->Tsp null rank sX == 0'); end;
if ~isempty(c) && spm_sp('size',sX,2) ~= size(c,1),
   error(' c->TSp matrix & contrast dimensions don''t match');
end
%--------- end argument check ---------------------------------

%- project c onto the space of  X' if needed
%-------------------------------------------
if ~isempty(c) && ~spm_sp('isinspp',sX,c),
   warning([sprintf('\n') 'c is not a proper contrast in ' action ...
            ' in ' mfilename sprintf('\n') '!!! projecting...' ]);
   disp('from'), c, disp('to'), c = spm_sp('oPp:',sX,c)
end

cukFlag = strcmp(lower(action),'+c->tsp');

switch nargout
% case 0
%   warning(['no output demanded in ' mfilename ' ' action])
case {0,1}
   if ~isempty(c) && any(any(c))               %- c not empty & not null
      if cukFlag, varargout = { spm_sp('cukxp-:',sX,c) };
      else        varargout = { spm_sp('xp-:',sX,c) };
      end
   else if isempty(c), varargout = { [] };     %- c empty
       else                                    %- c null
           if cukFlag, varargout = { spm_sp('cukx',sX,c) };
           else        varargout = { spm_sp('x',sX)*c };
           end
       end
   end

case 2
   if ~isempty(c) && any(any(c))         %- not empty and not null
      if cukFlag,
         varargout = {
        spm_sp('cukxp-:',sX,c), ...      %- X1o
        spm_sp('cukx',sX,spm_sp('r',spm_sp('set',c))) };      %- X0
      else
         varargout = {
        spm_sp(':',sX, spm_sp('xp-:',sX,c)), ...              %- X1o
        spm_sp(':',sX, ...
               spm_sp('x',sX)*spm_sp('r',spm_sp('set',c))) }; %- X0
      end
   else
      if isempty(c),                     %- empty
         if cukFlag, varargout = { [], spm_sp('cukx',sX) };
         else        varargout = { [], spm_sp('x',sX) };
         end
      else                               %- null
         if cukFlag,
            varargout = { spm_sp(':',sX,spm_sp('cukx',sX,c)), ...
                          spm_sp(':',sX,spm_sp('cukx',sX)) };
         else
            varargout = { spm_sp('x',sX)*c, spm_sp('x',sX)};
         end
      end;
   end

otherwise
   error(['wrong number of output argument in ' action]);
end

case {'i0->x1o','+i0->x1o'} %- Space tested whilst keeping size of X(i0)
%=======================================================================
% X1o = spm_SpUtil('i0->X1o',sX,i0)

% arguments are checked in calls to spm_Util
%--------------------------------------------
if nargin<3, error('Insufficient arguments'),
else sX = varargin{2}; i0 = varargin{3}; end;

cukFlag = strcmp(lower(action),'+i0->x1o');

c  = spm_SpUtil('i0->c',sX,i0);

if cukFlag,
   varargout = { spm_SpUtil('+c->TSp',sX,c) };
else
   varargout = { spm_SpUtil('c->TSp',sX,c) };
end

case {'i0->c'}                 %-
%=======================================================================
% c = spm_SpUtil('i0->c',sX,i0)
%
% if i0 == [] : returns a proper contrast
% if i0 == [1:size(sX.X,2)] : returns [];
%
%- Algorithm : avoids the pinv(X0) and insure consistency
%- Get the estimable parts of c0 and c1
%- remove from c1_estimable the estimable part of c0.
%- Use the rotation making X1o orthog. to X0.
%- i0 is checked when Fc is created
%- If i0 defines a space that is the space of X but with
%- fewer vectors, c is null.

%--------- begin argument check --------------------------------
if nargin<3, error('Insufficient arguments'),
else sX = varargin{2}; i0 = varargin{3}; end;
if ~spm_sp('isspc',sX),  sX = spm_sp('set',varargin{2}); end;
if spm_sp('rk',sX) == 0, error('i0->c null rank sX == 0'); end;
sL  = spm_sp('size',sX,2);
i0  = sf_check_i0(i0,sL);
%--------- end argument check ----------------------------------

c0  = eye(sL); c0 = c0(:,i0);
c1  = eye(sL); c1 = c1(:,setdiff(1:sL,i0));

%- try to avoid the matlab error when doing svd of matrices with
%- high multiplicities. (svd convergence pb)

if ~ spm_sp('isinspp',sX,c0), c0 = spm_sp('oPp:',sX,c0); end;
if ~ spm_sp('isinspp',sX,c1), c1 = spm_sp('oPp:',sX,c1); end;

if ~isempty(c1)
   if ~isempty(c0)
      %- varargout = { spm_sp('res',spm_sp('set',opp*c0),opp*c1) };
      %- varargout = { c1 - c0*pinv(c0)*c1 }; NB: matlab pinv uses
      %- svd: will fail if spm_sp('set')  fails.

      varargout = { spm_sp('r:',spm_sp('set',c0),c1) };

   else varargout = { spm_sp('xpx',sX) }; end;
else
   varargout = { [] };  %- not zeros(sL,1) : this is return when
            %- appropriate
end

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case {'+x0->c','x0->c'}             %-
%=======================================================================
% c = spm_SpUtil('X0->c',sX,X0)
% c = spm_SpUtil('+X0->c',sX,cukX0)
% + version of 'x0->c'.
% The + version returns the same in the base u(:,1:r).

warning('Not tested for release - provided for completeness');
cukFlag = strcmp(lower(action),'+x0->c');

%--------- begin argument check ---------
if nargin<3, error('Insufficient arguments'),
else
   sX = varargin{2};
   if cukFlag, cukX0 = varargin{3}; else X0 = varargin{3}; end
end
if ~spm_sp('isspc',sX),  sX = spm_sp('set',varargin{2}); end
if spm_sp('rk',sX) == 0, error(['null rank sX == 0 in ' action]); end
if cukFlag
   if ~isempty(cukX0) && spm_sp('rk',sX) ~= size(cukX0,1),
      cukX0, spm_sp('rk',sX),
      error(['cukX0 of wrong size ' mfilename ' ' action]), end
else
   if ~isempty(X0) && spm_sp('size',sX,1) ~= size(X0,1),
      X0, spm_sp('size',sX,1),
      error(['X0 of wrong size ' mfilename ' ' action]),X0, end
end
%--------- end argument check ---------

if cukFlag
   if isempty(cukX0), X0 = []; else X0 = spm_sp('ox',sX)*cukX0; end
end

varargout = { sf_X0_2_c(X0,sX) };

case {'c->h','betarc'}  %-Extra sum of squares matrix for beta's from
                        %- contrast : use F-contrast if possible
%=======================================================================
% H = spm_SpUtil('c->H',sX,c)
error(' Obsolete : Use F-contrast utilities  ''H'' or ''Hsqr''... ');

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

%=======================================================================
%=======================================================================
%       trace part
%=======================================================================
%=======================================================================
%

case 'trrv'                      %-Traces for (effective) df calculation
%=======================================================================
% [trRV,trRVRV]= spm_SpUtil('trRV',x[,V])

if nargin == 1, error('insufficient arguments');
else sX = varargin{2};  end;

if ~spm_sp('isspc',sX), sX = spm_sp('Set',sX); end;

rk = spm_sp('rk',sX);
sL = spm_sp('size',sX,1);

if  sL == 0,
    warning('space with no dimension ');
    if nargout==1, varargout = {[]};
    else varargout = {[], []}; end
else

   if nargin > 2 && ~isempty(varargin{3})

    V = varargin{3};
    u = sX.u(:,1:rk);
    clear sX;
    if nargout==1
        %-only trRV needed
        if rk==0 || isempty(rk),  trMV = 0;
        else trMV = sum(sum( u .* (V*u) ));
        end
        varargout = { trace(V) - trMV};
    else
        %-trRVRV is needed as well
        if rk==0 || isempty(rk),
            trMV = 0;
            trRVRV = (norm(V,'fro'))^2;
         trV = trace(V);
         clear V u
        else
           Vu = V*u;
           trV = trace(V);
           trRVRV = (norm(V,'fro'))^2;
                   clear V;
           trRVRV = trRVRV - 2*(norm(Vu,'fro'))^2;
           trRVRV = trRVRV + (norm(u'*Vu,'fro'))^2;
           trMV = sum(sum( u .* Vu ));
                   clear u Vu
        end
        varargout = {(trV - trMV), trRVRV};
    end

   else  %- nargin == 2 | isempty(varargin{3})

    if nargout==1
        if rk==0 || isempty(rk), varargout = {sL};
        else varargout = {sL - rk};
        end
    else
        if rk==0 || isempty(rk),  varargout = {sL,sL};
        else varargout = {sL - rk, sL - rk};
        end
    end

    end
end

case 'trmv'                     %-Traces for (effective) Fdf calculation
%=======================================================================
% [trMV, trMVMV]] = spm_SpUtil('trMV',sX [,V])
%
% NB : When V is given empty, the routine asssumes it's identity
% This is used in spm_FcUtil.

if nargin == 1, error('insufficient arguments');
else sX = varargin{2}; end;
if ~spm_sp('isspc',sX), sX = spm_sp('Set',sX); end;
rk = spm_sp('rk',sX);

if isempty(rk)
    warning('Rank is empty');
    if nargout==1, varargout = {[]};
    else varargout = {[], []}; end
    return;
elseif  rk==0, warning('Rank is null in spm_SpUtil trMV ');
    if nargout==1, varargout = {0};
    else varargout = {0, 0}; end
    return;
end;

if nargin > 2 && ~isempty(varargin{3}) %- V provided, and assumed correct !

    V = varargin{3};
    u = sX.u(:,1:rk);
    clear sX;

    if nargout==1
        %-only trMV needed
        trMV = sum(sum(u' .* (u'*V) ));
        varargout = {trMV};
    else
        %-trMVMV is needed as well
        Vu = V*u;
                clear V
        trMV = sum(sum( u .* Vu ));
        trMVMV = (norm(u'*Vu,'fro'))^2;
            clear u Vu
        varargout = {trMV, trMVMV};
    end

else  % nargin == 2 | isempty(varargin{3}) %-no V specified: trMV == trMVMV
    if nargout==1
        varargout = {rk};
    else
        varargout = {rk, rk};
    end
end

case {'i0->edf','edf'}                  %-Effective F degrees of freedom
%=======================================================================
% [df1,df2] = spm_SpUtil('i0->edf',sX,i0,V)
%-----------------------------------------------------------------------
%--------- begin argument check ----------------------------------------
if nargin<3, error('insufficient arguments'),
else i0 = varargin{3}; sX = varargin{2}; end
if ~spm_sp('isspc',sX), sX = spm_sp('Set',sX); end;
i0  = sf_check_i0(i0,spm_sp('size',sX,2));
if nargin == 4, V=varargin{4}; else V = eye(spm_sp('size',sX,1)); end;
if nargin>4, error('Too many input arguments'), end;
%--------- end argument check ------------------------------------------

warning(' Use F-contrast utilities if possible ... ');

[trRV,trRVRV]    = spm_SpUtil('trRV', sX, V);
[trMpV,trMpVMpV] = spm_SpUtil('trMV',spm_SpUtil('i0->x1o',sX, i0),V);
varargout = {trMpV^2/trMpVMpV, trRV^2/trRVRV};

%=======================================================================
%=======================================================================
%       Utilities
%=======================================================================
%=======================================================================

case 'size'                                      %-Size of design matrix
%=======================================================================
% sz = spm_SpUtil('size',x,dim)

if nargin<3, dim=[]; else dim = varargin{3}; end
if nargin<2, error('insufficient arguments'), end

if isstruct(varargin{2})
   if isfield(varargin{2},'X')
    sz = size(varargin{2}.X);
   else error('no X field'); end;
else
    sz = size(varargin{2});
end

if ~isempty(dim)
    if dim>length(sz), sz = 1; else sz = sz(dim); end
    varargout = {sz};
elseif nargout>1
    varargout = cell(1,min(nargout,length(sz)));
    for i=1:min(nargout,length(sz)), varargout{i} = sz(i); end
else
    varargout = {sz};
end

case 'ix0check'                                      %-
%=======================================================================
% i0c = spm_SpUtil('iX0check',i0,sL)

if nargin<3, error('insufficient arguments'),
else i0 = varargin{2}; sL = varargin{3}; end;

varargout = {sf_check_i0(i0,sL)};

otherwise
%=======================================================================
error('Unknown action string in spm_SpUtil')

%=======================================================================
end

%=======================================================================
function i0c = sf_check_i0(i0,sL)
% NB : [] = sf_check_i0([],SL);
%

if all(ismember(i0,[0,1])) && length(i0(:))==sL, i0c=find(i0);
elseif ~isempty(i0) && any(floor(i0)~=i0) || any(i0<1) || any(i0>sL)
    error('logical mask or vector of column indices required')
else i0c = i0; end

%=======================================================================
function c = sf_X0_2_c(X0,sX)
%
%- Algorithm to avoids the pinv(X0) and insure consistency
%- Get a contrast that span the space of X0 and is estimable
%- Get the orthogonal complement and project onto the estimable space
%- Strip zeros columns and use the rotation making X1o orthog. to X0
% !!! tolerance dealing ?

if ~isempty(X0)

   sc0 = spm_sp('set',spm_sp('x-',sX,X0));
   if  sc0.rk
      c = spm_sp('oPp:',sX,spm_sp('r',sc0));
   else
      c = spm_sp('oPp',sX);
   end;
   c  = c(:,any(c));
   sL = spm_sp('size',sX,2);

   %- why the   "& size(X0,2) ~= sL"   !!!?
   if isempty(c) && size(X0,2) ~= sL
      c = zeros(sL,1);
   end

else
   c = spm_sp('xpx',sX);
end

%- c = spm_sp('r',sc0,spm_sp('oxp',sX)); would also works.


% Copyright (C) 2018  Symeon Symeonidis, Stefanos Tsantilas, Stelios Mitilineos
% simos421@gmail.com, steftsantilas@gmail.com, smitil@gmail.com
% 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.

function CstMeshInitiator(mws)

%' switch on FD-TET setting for accurate farfields

FDSolver = invoke(mws,'FDSolver');
invoke(FDSolver,'ExtrudeOpenBC','True');

Mesh = invoke(mws,'Mesh');
invoke(Mesh,'FPBAAvoidNonRegUnite','True');
invoke(Mesh,'ConsiderSpaceForLowerMeshLimit','False');
invoke(Mesh,'MinimumStepNumber','5');

MeshSettings = invoke(mws,'MeshSettings');
invoke(MeshSettings, 'SetMeshType','Hex');
invoke(MeshSettings, 'Set','RatioLimitGeometry','20');
MeshSettings = invoke(mws,'MeshSettings');
invoke(MeshSettings, 'SetMeshType','HexTLM');
invoke(MeshSettings, 'Set','RatioLimitGeometry','20');

PostProcess1D = invoke(mws,'PostProcess1D');
invoke(PostProcess1D,'ActivateOperation','vswr','true');
invoke(PostProcess1D,'ActivateOperation','yz-matrices','true');
end