function con = spm_cfg_con
% SPM Configuration file for contrast specification
%__________________________________________________________________________
% Copyright (C) 2005-2016 Wellcome Trust Centre for Neuroimaging

% $Id: spm_cfg_con.m 6952 2016-11-25 16:03:13Z guillaume $

%--------------------------------------------------------------------------
% spmmat Select SPM.mat
%--------------------------------------------------------------------------
spmmat         = cfg_files;
spmmat.tag     = 'spmmat';
spmmat.name    = 'Select SPM.mat';
spmmat.help    = {'Select SPM.mat file for contrasts.'};
spmmat.filter  = 'mat';
spmmat.ufilter = '^SPM\.mat$';
spmmat.num     = [1 1];

%--------------------------------------------------------------------------
% name Name
%--------------------------------------------------------------------------
name         = cfg_entry;
name.tag     = 'name';
name.name    = 'Name';
name.help    = {'Name of contrast.'};
name.strtype = 's';
name.num     = [1 Inf];

%--------------------------------------------------------------------------
% convec T-contrast weights vector
%--------------------------------------------------------------------------
convec         = cfg_entry;
convec.tag     = 'weights';
convec.name    = 'Weights vector';
convec.help    = {
    'Enter T-contrast weights vector.'
    'This is done similarly to the contrast manager. A 1 x n vector should be entered for T-contrasts.'
    'Contrast weight vectors will be padded with zeros to the correct length.'
    };
convec.strtype = 'r';
convec.num     = [1 Inf];

%--------------------------------------------------------------------------
% sessrep Replicate over sessions
%--------------------------------------------------------------------------
sessrep         = cfg_menu;
sessrep.tag     = 'sessrep';
sessrep.name    = 'Replicate over sessions';
sessrep.val = {'none'};
sessrep.help    = {
    'If there are multiple sessions with identical conditions, one might want to specify contrasts which are identical over sessions. This can be done automatically based on the contrast spec for one session.'
    'Contrasts can be either replicated (thus testing average effects over sessions) or created per session. In both cases, zero padding up to the length of each session and the block effects is done automatically. In addition, weights of replicated contrasts can be scaled by the number of sessions. This allows to use the same contrast manager batch for fMRI analyses with a variable number of sessions. The scaled contrasts can then be compared in a 2nd level model without a need for further adjustment of effect sizes.'
    };
sessrep.labels = {
    'Don''t replicate'
    'Replicate'
    'Replicate&Scale'
    'Create per session'
    'Both: Replicate + Create per session'
    'Both: Replicate&Scale + Create per session'
    }';
sessrep.values = {
    'none'
    'repl'
    'replsc'
    'sess'
    'both'
    'bothsc'
    }';

%==========================================================================
% tcon T-contrast
%==========================================================================
tcon      = cfg_branch;
tcon.tag  = 'tcon';
tcon.name = 'T-contrast';
tcon.val  = {name convec sessrep};
tcon.help = {
    '* Simple one-dimensional contrasts for an SPM{T}'
    ''
    'A simple contrast for an SPM{T} tests the null hypothesis c''B=0 against the one-sided alternative c''B>0, where c is a column vector. '
    ''
    '    Note that throughout SPM, the transpose of the contrast weights is used for display and input. That is, you''ll enter and visualise c''. For an SPM{T} this will be a row vector.'
    ''
    'For example, if you have a design in which the first two columns of the design matrix correspond to the effects for "baseline" and "active" conditions respectively, then a contrast with weights c''=[-1,+1,0,...] (with zero weights for any other parameters) tests the hypothesis that there is no "activation" (the parameters for both conditions are the same), against the alternative that there is some activation (i.e. the parameter for the "active" condition is greater than that for the "baseline" condition). The resulting SPM{T} (created by spm_getSPM.m) is a statistic image, with voxel values the value of the t-statistic for the specified contrast at that location. Areas of the SPM{T} with high voxel values indicate evidence for "activation". To look for areas of relative "de-activation", the inverse contrast could be used c''=[+1,-1,0,...].'
    ''
    'Similarly, if you have a design where the third column in the design matrix is a covariate, then the corresponding parameter is essentially a regression slope, and a contrast with weights c''=[0,0,1,0,...] (with zero weights for all parameters but the third) tests the hypothesis of zero regression slope, against the alternative of a positive slope. This is equivalent to a test no correlation, against the alternative of positive correlation. If there are other terms in the model beyond a constant term and the covariate, then this correlation is apartial correlation, the correlation between the data Y and the covariate, after accounting for the other effects.'
    }';

%--------------------------------------------------------------------------
% name Name
%--------------------------------------------------------------------------
name         = cfg_entry;
name.tag     = 'name';
name.name    = 'Name';
name.help    = {'Name of contrast.'};
name.strtype = 's';
name.num     = [1 Inf];

%--------------------------------------------------------------------------
% convec F-contrast weights matrix
%--------------------------------------------------------------------------
convec         = cfg_entry;
convec.tag     = 'weights';
convec.name    = 'Weights matrix';
convec.help    = {
    'Enter F-contrast weights matrix.'
    'This is done similarly to the contrast manager.'
    'Contrast weight matrices will be padded with zeros to the correct length.'
    };
convec.strtype = 'r';
convec.num     = [Inf Inf];

%==========================================================================
% fcon F-contrast
%==========================================================================
fcon      = cfg_branch;
fcon.tag  = 'fcon';
fcon.name = 'F-contrast';
fcon.val  = {name convec sessrep};
fcon.help = {
    '* Linear constraining matrices for an SPM{F}'
    ''
    'The null hypothesis c''B=0 can be thought of as a (linear) constraint on the full model under consideration, yielding a reduced model. Taken from the viewpoint of two designs, with the full model an extension of the reduced model, the null hypothesis is that the additional terms in the full model are redundent.'
    ''
    'Statistical inference proceeds by comparing the additional variance explained by full design over and above the reduced design to the error variance (of the full design), an "Extra Sum-of-Squares" approach yielding an F-statistic for each voxel, whence an SPM{F}.'
    ''
    'This is useful in a number of situations:'
    ''
    '* Two sided tests'
    ''
    'The simplest use of F-contrasts is to effect a two-sided test of a simple linear contrast c''B, where c is a column vector. The SPM{F} is the square of the corresponding SPM{T}. High values of the SPM{F} therefore indicate evidence against the null hypothesis c''B=0 in favour of the two-sided alternative c''B~=0.'
    ''
    '* General linear hypotheses'
    ''
    'Where the contrast weights is a matrix, the rows of the (transposed) contrast weights matrix c'' must define contrasts in their own right, and the test is effectively simultaneously testing the null hypotheses associated with the individual component contrasts with weights defined in the rows. The null hypothesis is still c''B=0, but since c is a matrix, 0 here is a zero vector rather than a scalar zero, asserting that under the null hypothesis all the component hypotheses are true.'
    ''
    'For example: Suppose you have a language study with 3 word categories (A,B & C), and would like to test whether there is any difference at all between the three levels of the "word category" factor.'
    ''
    'The design matrix might look something like:'
    ''
    '         [ 1 0 0 ..]'
    '         [ : : : ..]'
    '         [ 1 0 0 ..]'
    '         [ 0 1 0 ..]'
    '    X =  [ : : : ..]'
    '         [ 0 1 0 ..]'
    '         [ 0 0 1 ..]'
    '         [ : : : ..]'
    '         [ 0 0 1 ..]'
    '         [ 0 0 0 ..]'
    '         [ : : : ..]'
    ''
    ' ...with the three levels of the "word category" factor modelled in the  first three columns of the design matrix.'
    ''
    'The matrix of contrast weights will look like:'
    ''
    ' c'' = [1 -1  0 ...;'
    '       0  1 -1 ...]'
    ''
    'Reading the contrasts weights in each row of c'', we see that row 1 states that category A elicits the same response as category B, row 2 that category B elicits the same response as category C, and hence together than categories A, B & C all elicit the same response.'
    ''
    'The alternative hypothesis is simply that the three levels are not all the same, i.e. that there is some difference in the paraeters for the three levels of the factor: The first and the second categories produce different brain responses, OR the second and third categories, or both.'
    ''
    'In other words, under the null hypothesis (the categories produce the same brain responses), the model reduces to one in which the three level "word category" factor can be replaced by a single "word" effect, since there is no difference in the parameters for each category. The corresponding design matrix would have the first three columns replaced by a single column that is the sum (across rows) of the first three columns in the design matric above, modelling the brain response to a word, whatever is the category. The F-contrast above is in fact testing the hypothesis that this reduced design doesn''t account for significantly less variance than the full design with an effect for each word category.'
    ''
    'Another way of seeing that, is to consider a reparameterisation of the model, where the first column models effects common to all three categories, with the second and third columns modelling the differences between the three conditions, for example:'
    ''
    '         [ 1  1  0 ..]'
    '         [ :  :  : ..]'
    '         [ 1  1  0 ..]'
    '         [ 1  0  1 ..]'
    '    X =  [ :  :  : ..]'
    '         [ 1  0  1 ..]'
    '         [ 1 -1 -1 ..]'
    '         [ :  :  : ..]'
    '         [ 1 -1 -1 ..]'
    '         [ 0  0  0 ..]'
    '         [ :  :  : ..]'
    ''
    'In this case, an equivalent F contrast is of the form'
    ' c'' = [ 0 1 0 ...;'
    '        0 0 1 ...]'
    'and would be exactly equivalent to the previous contrast applied to the previous design. In this latter formulation, you are asking whewher the two columns modelling the "interaction space" account for a significant amount of variation (variance) of the data. Here the component contrasts in the rows of c'' are simply specifying that the parameters for the corresponding rows are are zero, and it is clear that the F-test is comparing this full model with a reduced model in which the second and third columns of X are omitted.'
    ''
    '    Note the difference between the following two F-contrasts:'
    '         c'' = [ 0 1 0 ...;     (1)'
    '                0 0 1 ...]'
    '     and'
    '         c'' = [ 0 1 1 ...]     (2)'
    ''
    '    The first is an F-contrast, testing whether either of the parameters for the effects modelled in the 2nd & 3rd columns of the design matrix are significantly different from zero. Under the null hypothesis c''B=0, the first contrast imposes a two-dimensional constraint on the design. The second contrast tests whether the SUM of the parameters for the 2nd & 3rd columns is significantly different from zero. Under the null hypothesis c''B=0, this second contrast only imposes a one dimensional constraint on the design.'
    ''
    '    An example of the difference between the two is that the first contrast would be sensitive to the situation where the 2nd & 3rd parameters were +a and -a, for some constant a, wheras the second contrast would not detect this, since the parameters sum to zero.'
    ''
    'The test for an effect of the factor "word category" is an F-test with 3-1=2 "dimensions", or degrees of freedom.'
    ''
    '* Testing the significance of effects modelled by multiple columns'
    ''
    'A conceptially similar situation arises when one wonders whether a set of coufound effects are explaining any variance in the data. One important advantage of testing the with F contrasts rather than one by one using SPM{T}''s is the following. Say you have two covariates that you would like to know whether they can "predict" the brain responses, and these two are correlated (even a small correlation would be important in this instance). Testing one and then the other may lead you to conclude that there is no effect. However, testing with an F test the two covariates may very well show a not suspected effect. This is because by testing one covariate after the other, one never tests for what is COMMON to these covariates (see Andrade et al, Ambiguous results in functional neuroimaging, NeuroImage, 1999).'
    ''
    ''
    'More generally, F-tests reflect the usual analysis of variance, while t-tests are traditionally post hoc tests, useful to see in which direction is an effect going (positive or negative). The introduction of F-tests can also be viewed as a first means to do model selection.'
    ''
    ''
    'Technically speaking, an F-contrast defines a number of directions (as many as the rank of the contrast) in the space spanned by the column vectors of the design matrix. These directions are simply given by X*c if the vectors of X are orthogonal, if not, the space define by c is a bit more complex and takes care of the correlation within the design matrix. In essence, an F-contrast is defining a reduced model by imposing some linear constraints (that have to be estimable, see below) on the parameters estimates. Sometimes, this reduced model is simply made of a subset of the column of the original design matrix but generally, it is defined by a combination of those columns. (see spm_FcUtil for what (I hope) is an efficient handling of F-contrats computation).'
    }';

%--------------------------------------------------------------------------
% name Name
%--------------------------------------------------------------------------
name         = cfg_entry;
name.tag     = 'name';
name.name    = 'Name';
name.help    = {'Name of contrast.'};
name.strtype = 's';
name.num     = [1 Inf];

%--------------------------------------------------------------------------
% conweight Contrast weight
%--------------------------------------------------------------------------
conweight         = cfg_entry;
conweight.tag     = 'conweight';
conweight.name    = 'Contrast weight';
conweight.help    = {'The contrast weight for the selected column.'};
conweight.strtype = 'r';
conweight.num     = [1 1];

%--------------------------------------------------------------------------
% colcond Condition #
%--------------------------------------------------------------------------
colcond         = cfg_entry;
colcond.tag     = 'colcond';
colcond.name    = 'Condition #';
colcond.help    = {'Select which condition function set is to be contrasted.'};
colcond.strtype = 'n';
colcond.num     = [1 1];

%--------------------------------------------------------------------------
% colbf Basis function #
%--------------------------------------------------------------------------
colbf         = cfg_entry;
colbf.tag     = 'colbf';
colbf.name    = 'Basis function #';
colbf.help    = {'Select which basis function from the basis function set is to be contrasted.'};
colbf.strtype = 'n';
colbf.num     = [1 1];

%--------------------------------------------------------------------------
% colmod Parametric modulation #
%--------------------------------------------------------------------------
colmod         = cfg_entry;
colmod.tag     = 'colmod';
colmod.name    = 'Parametric modulation #';
colmod.help    = {'Select which parametric modulation is to be contrasted. If there is no time/parametric modulation, enter "1". If there are both time and parametric modulations, then time modulation comes before parametric modulation.'};
colmod.strtype = 'n';
colmod.num     = [1 1];

%--------------------------------------------------------------------------
% colmodord Parametric modulation order
%--------------------------------------------------------------------------
colmodord         = cfg_entry;
colmodord.tag     = 'colmodord';
colmodord.name    = 'Parametric modulation order';
colmodord.help    = {
    'Order of parametric modulation to be contrasted. '
    ''
    '0 - the basis function itself, 1 - 1st order mod etc'
    }';
colmodord.strtype = 'w';
colmodord.num     = [1 1];

%--------------------------------------------------------------------------
% colconds Contrast entry
%--------------------------------------------------------------------------
colconds      = cfg_branch;
colconds.tag  = 'colconds';
colconds.name = 'Contrast entry';
colconds.val  = {conweight colcond colbf colmod colmodord};
colconds.help = {''};

%--------------------------------------------------------------------------
% generic T contrast for conditions
%--------------------------------------------------------------------------
generic        = cfg_repeat;
generic.tag    = 'generic';
generic.name   = 'T contrast for conditions';
generic.help   = {'Assemble your contrast column by column.'};
generic.values = {colconds};
generic.val    = {colconds};
generic.num    = [1 Inf];

%--------------------------------------------------------------------------
% colreg T contrast for extra regressors
%--------------------------------------------------------------------------
colreg         = cfg_entry;
colreg.tag     = 'colreg';
colreg.name    = 'T contrast for extra regressors';
colreg.help    = {'Enter T contrast vector for extra regressors.'};
colreg.strtype = 'r';
colreg.num     = [1 Inf];

%--------------------------------------------------------------------------
% coltype Contrast columns
%--------------------------------------------------------------------------
coltype        = cfg_choice;
coltype.tag    = 'coltype';
coltype.name   = 'Contrast columns';
coltype.val    = {generic };
coltype.help   = {'Contrasts can be specified either over conditions or over extra regressors.'};
coltype.values = {generic colreg };

%--------------------------------------------------------------------------
% sessions Session(s)
%--------------------------------------------------------------------------
sessions         = cfg_entry;
sessions.tag     = 'sessions';
sessions.name    = 'Session(s)';
sessions.help    = {'Enter session number(s) for which this contrast should be created. If more than one session number is specified, the contrast will be an average contrast over the specified conditions or regressors from these sessions.'};
sessions.strtype = 'n';
sessions.num     = [1 Inf];

%==========================================================================
% tconsess T-contrast (cond/sess based)
%==========================================================================
tconsess         = cfg_branch;
tconsess.tag     = 'tconsess';
tconsess.name    = 'T-contrast (cond/sess based)';
tconsess.val     = {name coltype sessions};
tconsess.help    = {
    'Define a contrast in terms of conditions or regressors instead of columns of the design matrix. This allows to create contrasts automatically even if some columns are not always present (e.g. parametric modulations).'
    ''
    'Each contrast column can be addressed by specifying'
    '* session number'
    '* condition number'
    '* basis function number'
    '* parametric modulation number and'
    '* parametric modulation order.'
    ''
    'If the design is specified without time or parametric modulation, SPM creates a "pseudo-modulation" with order zero. To put a contrast weight on a basis function one therefore has to enter "1" for parametric modulation number and "0" for parametric modulation order.'
    ''
    'Time and parametric modulations are not distinguished internally. If time modulation is present, it will be parametric modulation "1", and additional parametric modulations will be numbered starting with "2".'
    ''
    '* Simple one-dimensional contrasts for an SPM{T}'
    ''
    'A simple contrast for an SPM{T} tests the null hypothesis c''B=0 against the one-sided alternative c''B>0, where c is a column vector. '
    ''
    '    Note that throughout SPM, the transpose of the contrast weights is used for display and input. That is, you''ll enter and visualise c''. For an SPM{T} this will be a row vector.'
    ''
    'For example, if you have a design in which the first two columns of the design matrix correspond to the effects for "baseline" and "active" conditions respectively, then a contrast with weights c''=[-1,+1,0,...] (with zero weights for any other parameters) tests the hypothesis that there is no "activation" (the parameters for both conditions are the same), against the alternative that there is some activation (i.e. the parameter for the "active" condition is greater than that for the "baseline" condition). The resulting SPM{T} (created by spm_getSPM.m) is a statistic image, with voxel values the value of the t-statistic for the specified contrast at that location. Areas of the SPM{T} with high voxel values indicate evidence for "activation". To look for areas of relative "de-activation", the inverse contrast could be used c''=[+1,-1,0,...].'
    ''
    'Similarly, if you have a design where the third column in the design matrix is a covariate, then the corresponding parameter is essentially a regression slope, and a contrast with weights c''=[0,0,1,0,...] (with zero weights for all parameters but the third) tests the hypothesis of zero regression slope, against the alternative of a positive slope. This is equivalent to a test no correlation, against the alternative of positive correlation. If there are other terms in the model beyond a constant term and the covariate, then this correlation is apartial correlation, the correlation between the data Y and the covariate, after accounting for the other effects.'
    }';

%--------------------------------------------------------------------------
% consess Contrast Sessions
%--------------------------------------------------------------------------
consess        = cfg_repeat;
consess.tag    = 'consess';
consess.name   = 'Contrast Sessions';
consess.help   = {
    'For general linear model Y = XB + E with data Y, desgin matrix X, parameter vector B, and (independent) errors E, a contrast is a linear combination of the parameters c''B. Usually c is a column vector, defining a simple contrast of the parameters, assessed via an SPM{T}. More generally, c can be a matrix (a linear constraining matrix), defining an "F-contrast" assessed via an SPM{F}.'
    ''
    'The vector/matrix c contains the contrast weights. It is this contrast weights vector/matrix that must be specified to define the contrast. The null hypothesis is that the linear combination c''B is zero. The order of the parameters in the parameter (column) vector B, and hence the order to which parameters are referenced in the contrast weights vector c, is determined by the construction of the design matrix.'
    ''
    'There are two types of contrast in SPM: simple contrasts for SPM{T}, and "F-contrasts" for SPM{F}.'
    ''
    'For a thorough theoretical treatment, see the Human Brain Function book and the statistical literature referenced therein.'
    ''
    ''
    '* Non-orthogonal designs'
    ''
    'Note that parameters zero-weighted in the contrast are still included in the model. This is particularly important if the design is not orthogonal (i.e. the columns of the design matrix are not orthogonal). In effect, the significance of the contrast is assessed *after* accounting for the other effects in the design matrix. Thus, if two covariates are correlated, testing the significance of the parameter associated with one will only test for the part that is not present in the second covariate. This is a general point that is also true for F-contrasts. See Andrade et al, Ambiguous results in functional neuroimaging, NeuroImage, 1999, for a full description of the effect of non othogonal design testing.'
    ''
    ''
    '* Estimability'
    ''
    'The contrast c''B is estimated by c''b, where b are the parameter estimates given by b=pinv(X)*Y.'
    ''
    'However, if a design is rank-deficient (i.e. the columns of the design matrix are not linearly independent), then the parameters are not unique, and not all linear combinations of the parameter are valid contrasts, since contrasts must be uniquely estimable.'
    ''
    'A weights vector defines a valid contrast if and only if it can be constructed as a linear combination of the rows of the design matrix. That is c'' (the transposed contrast vector - a row vector) is in the row-space of the design matrix.'
    ''
    'Usually, a valid contrast will have weights that sum to zero over the levels of a factor (such as condition).'
    ''
    'A simple example is a simple two condition design including a constant, with design matrix'
    ''
    '          [ 1 0 1 ]'
    '          [ : : : ]'
    '     X =  [ 1 0 1 ]'
    '          [ 0 1 1 ]'
    '          [ : : : ]'
    '          [ 0 1 1 ]'
    ''
    'The first column corresponds to condition 1, the second to condition 2, and the third to a constant (mean) term. Although there are three columns to the design matrix, the design only has two degrees of freedom, since any one column can be derived from the other two (for instance, the third column is the sum of the first two). There is no unique set of parameters for this model, since for any set of parameters adding a constant to the two condition effects and subtracting it from the constant effect yields another set of viable parameters. However, the difference between the two condition effects is uniquely estimated, so c''=[-1,+1,0] does define a contrast.'
    ''
    'If a parameter is estimable, then the weights vector with a single "1" corresponding to that parameter (and zero elsewhere) defines a valid contrast.'
    ''
    ''
    '* Multiple comparisons'
    ''
    'Note that SPM implements no corrections to account for you looking at multiple contrasts.'
    ''
    'If you are interested in a set of hypotheses that together define a consistent question, then you should account for this when assessing the individual contrasts. A simple Bonferroni approach would assess N simultaneous contrasts at significance level alpha/N, where alpha is the chosen significance level (usually 0.05).'
    ''
    'For two sided t-tests using SPM{T}s, the significance level should be halved. When considering both SPM{T}s produced by a contrast and it''s inverse (the contrast with negative weights), to effect a two-sided test to look for both "increases" and "decreases", you should review each SPM{T} at at level 0.05/2 rather than 0.05. (Or consider an F-contrast!)'
    ''
    ''
    '* Contrast images and ESS images'
    ''
    'For a simple contrast, SPM (spm_getSPM.m) writes a contrast image: con_????.{img,nii}, with voxel values c''b. (The ???? in the image names are replaced with the contrast number.) These contrast images (for appropriate contrasts) are suitable summary images of an effect at this level, and can be used as input at a higher level when effecting a random effects analysis.'
    ''
    'For an F-contrast, SPM (spm_getSPM.m) writes the Extra Sum-of-Squares (the difference in the residual sums of squares for the full and reduced model) as ess_????.{img,nii}. (Note that the ess_????.{img,nii} and SPM{T,F}_????.{img,nii} images are not suitable input for a higher level analysis.)'
    }';
consess.values = {tcon fcon tconsess};
consess.num    = [0 Inf];

%--------------------------------------------------------------------------
% delete Delete existing contrasts
%--------------------------------------------------------------------------
delete        = cfg_menu;
delete.tag    = 'delete';
delete.name   = 'Delete existing contrasts';
delete.help   = {'Delete existing contrasts.'};
delete.labels = {'Yes', 'No'};
delete.values = {1 0};
delete.val    = {0};

%--------------------------------------------------------------------------
% con Contrast Manager
%--------------------------------------------------------------------------
con      = cfg_exbranch;
con.tag  = 'con';
con.name = 'Contrast Manager';
con.val  = {spmmat consess delete};
con.help = {'Specify T and F contrasts.'};
con.prog = @spm_run_con;
con.vout = @vout_stats;

%==========================================================================
function dep = vout_stats(job)
dep(1)            = cfg_dep;
dep(1).sname      = 'SPM.mat File';
dep(1).src_output = substruct('.','spmmat');
dep(1).tgt_spec   = cfg_findspec({{'filter','mat','strtype','e'}});
%dep(2)            = cfg_dep;
%dep(2).sname      = 'SPM Variable';
%dep(2).src_output = substruct('.','spmvar');
%dep(2).tgt_spec   = cfg_findspec({{'strtype','e'}});
dep(2)            = cfg_dep;
dep(2).sname      = 'All Con Images';
dep(2).src_output = substruct('.','con');
dep(2).tgt_spec   = cfg_findspec({{'filter','image','strtype','e'}});
dep(3)            = cfg_dep;
dep(3).sname      = 'All Stats Images';
dep(3).src_output = substruct('.','spm');
dep(3).tgt_spec   = cfg_findspec({{'filter','image','strtype','e'}});


function rxnLink = connectedRxnsByEFM(model, conComp, rxnInLoops, printLevel)
% Find reactions lying in internal cycles that are connected by any EFMs.
% Used for minimizing the number of constraints for the loopless requirement
% when running loopless FVA using localized loopless constraints. This
% function requires EFMtool (`CalculateFluxModes.m`) to work.
%
% USAGE:
%    rxnLink = connectedRxnsByEFM(model, conComp, rxnInLoops)
%
% INPUTS:
%    model:      COBRA model
%    conComp:    reactions connected in the minimal nullspace for internal cycles, computed by `connectedRxnsInNullSpace`
%    rxnInLoops: n-by-2 logical matrix where n = # of rxns in the model
%                rxnInLoops(k, 1) = true => forward direction of the k-th reaction in internal cycles
%                rxnInLoops(k, 2) = true => reverse direction of the k-th reaction in internal cycles
%                Returned by `findMinNull.m`
%
% OPTIONAL INPUT:
%    printLevel: true to show messages when the linkage matrix cannot be computed
%
% OUTPUT:
%    rxnLink:    n-by-n matrix. rxnLink(i, j) = 1 => reactions i and j are connected
%                by an EFM representing an elementary internal cycle.

if nargin < 4
    printLevel = 0;
end
% the path to EFMtool
efmToolpath = which('CalculateFluxModes.m');
if isempty(efmToolpath)
    rxnLink = [];
    if printLevel
        fprintf('EFMtool not in Matlab path. Unable to calculate EFMs.\n')
    end
    return
end
efmToolpath = strsplit(efmToolpath, filesep);
efmToolpath = strjoin(efmToolpath(1: end - 1), filesep);
p = pwd;
cd(efmToolpath)
% EFMtool call options
options = CreateFluxModeOpts('sign-only', true, 'level', 'WARNING');

rxnLink = sparse(size(model.S, 2), size(model.S, 2));
for jC = 1:max(conComp)
    % for each connected component, find the EFM matrix
    try
        S = model.S(:, conComp == jC);
        S = S(any(S, 2), :);
        % revert the stoichiometries for reactions that are in cycles only in the reverse direction
        S(:, rxnInLoops(conComp == jC, 1) & ~rxnInLoops(conComp == jC, 2)) = -S(:, rxnInLoops(conComp == jC, 1) & ~rxnInLoops(conComp == jC, 2));
        rev = all(rxnInLoops(conComp == jC, :), 2);
        efms = CalculateFluxModes(full(S), double(rev), options);
        % calling Java too rapidly may have problems in tests
        pause(1e-4)
        efms = efms.efms;
        rxnJC = find(conComp == jC);
        for j = 1:numel(rxnJC)
            rxnLink(rxnJC(j), rxnJC) = any(efms(:, efms(j, :) ~= 0), 2)';
        end
    catch msg
        if printLevel
            fprintf('Error encountered during calculation of EFMs:\n%s', getReport(msg))
        end
        rxnLink = [];
        return
    end
end
cd(p)

end


% EEGFILTFFT -  (high|low|band)-pass filter data using inverse fft
%                 (without using the Matlab signal processing toolbox)
% Usage:
%  >> [smoothdata] = eegfiltfft(data,srate,locutoff,hicutoff);
%  >> [smoothdata] = eegfiltfft(data,srate,locutoff,hicutoff,epochframes,filtorder,revfilt);
%
% Inputs:
%   data        = (channels,frames*epochs) data to filter
%   srate       = data sampling rate (Hz)
%   locutoff    = low-edge frequency in pass band (Hz)  {0 -> lowpass}
%   hicutoff    = high-edge frequency in pass band (Hz) {0 -> highpass}
%
% Optional inputs:
%   epochframes = frames per epoch (filter each epoch separately {def/0: data is 1 epoch}
%   filtorder   = argument not used (but required for symmetry with EEGFILT function).
%   revfilt     = [0|1] reverse filter (i.e. bandpass filter to notch filter). {0}
%
% Outputs:
%    smoothdata = smoothed data
%
% Known problems:
%    The signal drop off is much smaller compared to standard filtering methods
%
% Author: Arnaud Delorme, SCCN/INC/UCSD, La Jolla, 2003
%
% See also: EEGFILT

% inspired from a google group message
% http://groups.google.com/groups?q=without+%22the+signal+processing+toolbox%22&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=f56893ae.0311141025.3069d4f8%40posting.google.com&rnum=8

% Copyright (C) Arnaud Delorme, SCCN/INC/UCSD, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function smoothdata = eegfiltfft(data, fs, lowcut, highcut, epochframes, filtorder, revfilt);

    if nargin < 4
        help eegfiltfft;
    end
    [chans frames] = size(data);
    if nargin < 5 || epochframes == 0
        epochframes = frames;
    end
    if nargin < 7
        revfilt = 0;
    end

    epochs = frames/epochframes;
    if epochs ~= round(epochs)
        error('Epochframes does not divide the total number of frames');
    end
    fv=reshape([0:epochframes-1]*fs/epochframes,epochframes,1); % Frequency vector for plotting

    %figure;
    %plot(fv, 20*log(abs(X))/log(10))  % Plot power spectrum in dB scale
    %xlabel('Frequency [Hz]')
    %ylabel('Signal power [dB]')

    % find closest freq in fft decomposition
    % --------------------------------------
    if lowcut ~= 0
        [tmp idxl]=min(abs(fv-lowcut));  % Find the entry in fv closest to 5 kHz
    else
        idxl = 0;
    end
    if highcut ~= 0
        [tmp idxh]=min(abs(fv-highcut));  % Find the entry in fv closest to 5 kHz
    else
        idxh = ceil(length(fv)/2);
    end

    % filter the data
    % ---------------
    smoothdata = zeros(chans,frames);
    for e = 1:epochs                % filter each epoch, channel
        for c=1:chans
            X=fft(data(c,(e-1)*epochframes+1:e*epochframes));
            if revfilt
                X(idxl+1:idxh-1)=0;
                if mod(length(X),2) == 0
                    X(end/2:end)=0;
                else
                    X((end+1)/2:end)=0;
                end
            else
                X(1:idxl)=complex(0);
                X(end-idxl:end)=complex(0);
                X(idxh:end)=complex(0);
            end;
            smoothdata(c,(e-1)*epochframes+1:e*epochframes) = 2*real(ifft(X));
            if epochs == 1
                if rem(c,20) ~= 0
                    fprintf('.');
                else
                    fprintf('%d',c);
                end
            end
        end
    end
    fprintf('\n');


function planner(rows,cols,obs,start,goal)
%
% path planner simulator
%
density = size(obs,2)/(rows*cols);% find obstacle density
ndensity = 9;
for d = 9:10:89
    if d <= density
        ndensity = d;
    else
        break;
    end
end
csetname = sprintf('curveset_%d_%d_%d',rows,cols,ndensity);
if(evalin('base',sprintf('exist(''%s'',''var'')',csetname))==0)% try to load curveset from matlab runtime memory
    if(evalin('base',sprintf('exist(''%s.mat'',''file'')',csetname))==0)% try to load curveset from hard drive
        disp('Generating curve set');
        evalin('base',sprintf('gen_curves(%d,%d,%d)',rows,cols,ndensity));% generate curveset
    else
        disp('Loading curve set from file');
        evalin('base',sprintf('load %s.mat',csetname));
    end
    curveset = evalin('base', csetname);
else
    disp('Loading curve set from memory');
    curveset = evalin('base', csetname);
end
clear csetname;
sol1 = forward_chain(rows,cols,obs,goal,start,100);% find time to reach shallowest solution
if (sol1 == -1)
    disp('Run program after reloading world');% Dynamics changed
    return;
end
la = find_good_la(rows,cols,obs,goal,start,sol1,curveset);% estimate lookahead to use
world = extend_world(rows,cols,obs,goal,la);% extend world in time
pot_vals = calc_pot_values(world);% Calculate potential values
[res path] = traverse_world(start,pot_vals);% Follow negative potential gradient
if (res == 0)
    disp('Run program after reloading world');% Dynamics changed or Goal became unreachable
    return;
end
show_path(world,path)% display path traversed
end


function blur_img = synthesize_nonuniform_blur(img, info_data, gyro_data)

    img= im2double(img);

    bd = 20; %% tmp
    img_pad = padarray(img, [bd, bd], 'replicate', 'both');

    num_row = size(img_pad, 1);
    num_col = size(img_pad, 2);

    time_interval = 0.01;

    % set up start and end time
    st_time = info_data(1, 3) + (-8) * time_interval - info_data(1, 2);
    ed_time = info_data(1, 3) + (-8) * time_interval;

    valid_row = 1:size(gyro_data, 1);%find(gyro_data(:, end) < ed_time + time_interval);

    % interpolate
    portion = 3;%ceil(1/infoData(1,2));
    intervalAfterTime = time_interval/portion;

    % linear interpolation
    tempInd = 1:portion:1+(length(valid_row)-1)*portion;
    x = tempInd;
    v = gyro_data(valid_row,1:end);
    xq = 1:1+(length(valid_row)-1)*portion;
    vq = interp1(x,v,xq);
    gyroInterData = vq;

    % compute angular velocity
    avelInter = gyroInterData(2:end,4:6).*repmat((gyroInterData(2:end,end)- ...
        gyroInterData(1:end-1,end)),[1,3]);

    avelInter = cumsum(avelInter)/1;

    % switch the tx ty for headleft
    tmp = gyroInterData(:,1);
    gyroInterData(:,1) = -gyroInterData(:,2);
    gyroInterData(:,2) = tmp;

    % compute velocity
    comDrift = [0,0.00,0];
    velInter = (gyroInterData(2:end,1:3)-repmat(comDrift,[size(gyroInterData,1)-1,1]))...
        .*repmat((gyroInterData(2:end,end)- gyroInterData(1:end-1,end)),[1,3]);

    velInter = cumsum(velInter*9.8);

    % initial speed
    initialSpeed = [0,0,0];
    velInter = velInter + repmat(initialSpeed,[size(velInter,1),1]);

    % compute the position
    activeRow = intersect(find(gyroInterData(:,end)<ed_time+time_interval),...
        find(gyroInterData(:,end)>=st_time));
    gyroInterData = gyroInterData(activeRow,:);
    activeRow(end)=[];

    rotInter = avelInter(activeRow,:).*repmat((gyroInterData(2:end,end)...
        - gyroInterData(1:end-1,end)),[1,3]);
    rotInter = cumsum(rotInter);

    tranInter = velInter(activeRow,:).*repmat((gyroInterData(2:end,end)...
        - gyroInterData(1:end-1,end)),[1,3]);
    tranInter = cumsum(tranInter)/1;

    pixelPitch = 1e-5;
    poseInter = [tranInter,avelInter(activeRow,:)];
    poseInter = poseInter - repmat(poseInter(1,:),[size(poseInter,1),1]);

    if(1)
        factor = [1,1,1,-1,-1,-1];
    else
        factor = [1,1,1,1,1,1];
    end
    poseInter = poseInter.*repmat(factor,[size(poseInter,1),1]);

    ox = 0;
    oy = 0;
    rotCen = [0,0,0,ox,oy,0];
    poseInterOff = poseInter + repmat(rotCen,[size(poseInter,1),1]);

    fprintf('Generate local PSF...\n');

    data = poseInterOff;
    N_pose = size(data,1);
    weight = 1/N_pose;

    m = num_row;
    n = num_col;
    K = sparse([],[],[],m*n,m*n);

    for j = 1:N_pose
        pose = [data(j,4),data(j,5),data(j,6),data(j,1),data(j,2),data(j,3)];

        K_mat = compute_Kpose_6D(m,n,pose,1);

        K = K + weight * K_mat;
    end

    blur_img = img_pad;
    for c = 1:size(img_pad, 3)

        img_vector = img_pad(:, :, c);
        img_vector = K * img_vector(:);
        blur_img(:, :, c) = reshape(img_vector, num_row, num_col);

    end

    blur_img = blur_img(1+bd:end-bd, 1+bd:end-bd, :);

end


% GAINSANDREFERENCES compute gains matrices, references and regularization
%                    parameters for the controller for a specific robot

%% --- Initialization ---

% references for the CoM (sine trajectory)
Config.referencesCoM.amplitude = 0.02; %[m]
Config.referencesCoM.frequency = 0.25; %[Hz]
Config.referencesCoM.direction = [0;1;0];

% pseudoinverse tolerances
Config.Reg.pinv_tol        = 1e-4;
Config.Reg.pinvDampBaseVel = 1e-4;

% Gains matrices

% CoM gains
Config.Gain.KP_CoM    = diag([50;50;50]);
Config.Gain.KD_CoM    = 2*sqrt(Config.Gain.KP_CoM);

% Feet pose Gains
Config.Gain.KP_feet   = diag([50;50;50]);
Config.Gain.KD_feet   = 2*sqrt(Config.Gain.KP_feet);

% Postural task gains         % torso    % lArm       % rArm       % lLeg             % rLeg
Config.Gain.KP_joints = diag([20;20;20; 10;10;10;10; 10;10;10;10; 30;30;20;30;40;40; 30;30;20;30;40;40]);
Config.Gain.KD_joints = 2*sqrt(Config.Gain.KP_joints);


function tfrqview(tfr,sig,t,method,p1,p2,p3,p4,p5);
%TFRQVIEW Quick visualization of time-frequency representations.
%       TFRQVIEW(TFR,SIG,T,METHOD,P1,P2,P3,P4,P5) allows a quick
%       visualization of a time-frequency representation.
%
%       TFR     : time-frequency representation (MxN).
%       SIG     : signal in time. If unavailable, put sig=[] as input
%                 parameter.                    (default : []).
%       T       : time instants                 (default : 1:N).
%       METHOD  : name of chosen representation (default : 'TYPE1').
%                 See the TFR* files for authorized names.
%                 TYPE1 : the representation TFR goes in normalized
%                       frequency from -0.5 to 0.5 ;
%                 TYPE2 : the representation TFR goes in normalized
%                       frequency from 0 to 0.5.
%       P1...P5 : optional parameters of the representation : run the
%                 file TFRPARAM(METHOD) to know the meaning of P1..P5
%                 for your method.
%
%	When you use the 'save' option in the main menu, you save all your
%	variables as well as two strings, TfrQView and TfrView, in a mat
%	file. If you load this file and do eval(TfrQView), you will restart
%	the display session under tfrqview ; if you do eval(TfrView), you
%	will obtain the exact layout of the screen you had when clicking on
%	the 'save' button.
%
%       Example :
%        sig=fmsin(128); tfr=tfrwv(sig);
%        tfrqview(tfr,sig,1:128,'tfrwv');
%
%       See also TFRVIEW, TFRSAVE, TFRPARAM.

%       F. Auger, September 1994, July 1995
%       O. Lemoine, Oct 1995, May-July 1996.
%       Copyright (c) 1996 by CNRS (France).
%
%  This program is free software; you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation; either version 2 of the License, or
%  (at your option) any later version.
%
%  This program is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%  GNU General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program; if not, write to the Free Software
%  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

comp=computer;

% Tests on the input arguments
if nargin<1,
 error('At least one parameter required');
end
[tfrrow,tfrcol]=size(tfr);
if nargin==1,
 sig=[]; t=1:tfrcol; method='type1';
elseif nargin==2,
 t=1:tfrcol; method='type1';
elseif nargin==3,
 method='type1';
end
[trow,tcol] = size(t);
if (trow~=1),
 error('T must only have one row');
end;
if (tfrcol~=tcol),
 error('T must have as much elements as tfr has columns');
end;
method=upper(method);
[Nsig,Ncol]=size(sig);
if Ncol>2,
 error('SIG must have less than two columns');
end

% Computation of Nf2, the number of interresting points in frequency
method=upper(method);
if strcmp(method,'TFRWV'   ) | strcmp(method,'TFRPWV'  ) | ...
   strcmp(method,'TFRSPWV' ) | strcmp(method,'TFRCW'   ) | ...
   strcmp(method,'TFRZAM'  ) | strcmp(method,'TFRBJ'   ) | ...
   strcmp(method,'TFRBUD'  ) | strcmp(method,'TFRGRD'  ) | ...
   strcmp(method,'TFRRSPWV') | strcmp(method,'TFRRPWV' ) | ...
   strcmp(method,'TFRRIDB' ) | strcmp(method,'TFRRIDH' ) | ...
   strcmp(method,'TFRRIDT' ) | strcmp(method,'TFRASPW' ) | ...
   strcmp(method,'TFRDFLA' ) | strcmp(method,'TFRSPAW' ) | ...
   strcmp(method,'TFRRIDBN') | strcmp(method,'TFRUNTER') | ...
   strcmp(method,'TFRBERT' ) | strcmp(method,'TFRSCALO') | ...
   strcmp(method,'TYPE2'   ),
 Nf2=tfrrow;
elseif strcmp(method,'TFRPMH'  )| strcmp(method,'TFRRPMH' )| ...
       strcmp(method,'TFRSP'   )| strcmp(method,'TFRRSP'  )| ...
       strcmp(method,'TFRPPAGE')| strcmp(method,'TFRRPPAG')| ...
       strcmp(method,'TFRMHS'  )| strcmp(method,'TFRRGAB' )| ...
       strcmp(method,'TFRMH'   )| strcmp(method,'TFRMMCE' )| ...
       strcmp(method,'TFRRMSC' )| strcmp(method,'TFRPAGE' )| ...
       strcmp(method,'TFRGABOR')| strcmp(method,'TFRRI'   )| ...
       strcmp(method,'TFRMSC'  )| strcmp(method,'TYPE1'   )| ...
       strcmp(method,'TFRSTFT' ),
 Nf2=tfrrow/2;
else
 error('Unknown representation. Use type1 or type2');
end;

% Computation of freq (vector of frequency samples)
if strcmp(method,'TFRASPW' ) | strcmp(method,'TFRSCALO') | ...
   strcmp(method,'TFRDFLA' ) | strcmp(method,'TFRSPAW' ) | ...
   strcmp(method,'TFRUNTER') | strcmp(method,'TFRBERT' ),
 freq=eval(['p',num2str(nargin-4)]);   	% last input argument is freqs.
else
 freq=(0.5*(0:Nf2-1)/Nf2);
end

% Initialization of the current figure
zoom off; clf;
set(gcf,'Resize','On','NextPlot','Add');

% Initialization of the variables
if exist('options.mat'),
 load options
else
 threshold=5.0;
 linlogtfr=0;
 linlogspec=1;
 levelnumb=6;
 colmap=1;
 display=1;
 layout=1;
 iscolorbar=0;
 isgridsig=0;
 isgridspe=0;
 isgridtfr=0;
 issig=0;
 isspec=0;
end
choice=4;
Grid=1;
displayold=1;
fs=1.0;

if ((layout>=2 & layout<=4) & isempty(sig)),
 layout=1;
end

% Initialization of the axes
axcb   = axes('Units','normal','Visible','off','Box','On');
axsig  = axes('Units','normal','Visible','off','Box','On');
axspec = axes('Units','normal','Visible','off','Box','On');
axtfr  = axes('Units','normal','Visible','off','Box','On');
if comp(1:2)=='PC',
 set(axsig ,'fontsize',10);
 set(axspec,'fontsize',10);
 set(axtfr ,'fontsize',10);
end
set(gcf,'UserData',[axcb axsig axspec axtfr]);

% Test of analycity
if ~isempty(sig),
 for k=1:Ncol,
  spec(:,k)=abs(fft(sig(min(t):max(t),k))).^2; Nsp=length(spec);
  spec1=sum(spec(1:round(Nsp/2),k));
  spec2=sum(spec(round(Nsp/2)+1:Nsp,k));
  if spec2>spec1/10,
   disp('Be careful : the signal is not analytic!');
  end
 end
end

% Test of reality
if (Ncol==2 & ~isreal(tfr)),
 disp('Cross distribution. As the result is complex, we display the real part.');
 tfr=real(tfr);
end

while choice~=12,

 axes(axtfr);				% The current axis is the tfr axis

 if (display~=7 & choice~=2 & choice~=3 & choice<8),	% Call to tfrview
  linlog=linlogtfr+2*linlogspec;
  if choice==4,
   access=3;
  else
   access=1;
  end
  state=issig+2*iscolorbar;
  isgrid=isgridsig+2*isgridspe+4*isgridtfr;
  param = [display,linlog,threshold,levelnumb,Nf2,layout,access,state,fs,isgrid];
  map=colormap;
  if (nargin<=4),
   tfrview(tfr,sig,t,method,param,map);
  elseif (nargin==5),
   tfrview(tfr,sig,t,method,param,map,p1);
  elseif (nargin==6),
   tfrview(tfr,sig,t,method,param,map,p1,p2);
  elseif (nargin==7),
   tfrview(tfr,sig,t,method,param,map,p1,p2,p3);
  elseif (nargin==8),
   tfrview(tfr,sig,t,method,param,map,p1,p2,p3,p4);
  elseif (nargin==9),
   tfrview(tfr,sig,t,method,param,map,p1,p2,p3,p4,p5);
  end;
 elseif (display==7),			% keep in mind the last value of display
  display=displayold;
 end

 if (linlogtfr==0),			% Lin/log scale of the tfr
  linlogstr='Change to a logarithmic scale';
 else
  linlogstr='Change to a linear scale';
 end;

 % Main menu
 choice=menu ('TFRQVIEW MENU :',...
	      'Change the display mode',...
	      'Change the display layout',...
	      'Change the color map',...
	      'Change the sampling frequency',...
	      'Change the threshold',...
	      linlogstr,...
	      'Change the number of levels',...
	      'Grid',...
	      'Save',...
	      'Save options',...
	      'Print',...
	      'Close');

 if ((choice==9 | choice==11) & comp(1:2)~='PC'),
  if exist('workdir.mat'),
   load workdir;
  else
   Path=pwd;
   str1=[' The current directory is ',Path];
   disp(str1); disp('');
   continue=0;
   while continue==0,
    continue=1;
    str2=' Name of the directory (with full path) on which the files will be saved : ';
    disp(str2);
    PathWorkDir=input('       > ','s');
    if (exist(PathWorkDir)~=2),
     rep=input(' This directory doesn''t exist. Do you want to create it (y/n) ? ','s');
     if upper(rep)=='Y',
      eval(['!mkdir ',PathWorkDir]);
     else
      continue=0;
     end
    end
   end
   if PathWorkDir(length(PathWorkDir))~='/',
    PathWorkDir=[PathWorkDir,'/'];
   end
   save workdir PathWorkDir;
  end
 end

 if (choice==1), 			% Change the display mode

  display=menu('DISPLAY MODE :',...
	       'Contour',...
	       'Imagesc',...
	       'Pcolor',...
	       'Surf',...
	       'Mesh',...
	       'Cancel');

 elseif (choice==2), 			% Change the display layout

  layoutold=layout; indlo=1; layout=1;
  while layout~=6,			% While not close

   if ~iscolorbar,
    colorbarstr='Add a color bar';
   else
    colorbarstr='Remove the color bar';
   end
   if ~linlogspec,
    specstr='TFR + Spectrum (linear)';
    tfrsstr='TFR + Signal + Spectrum (linear)';
   else
    specstr='TFR + Spectrum (logarithmic)';
    tfrsstr='TFR + Signal + Spectrum (logarithmic)';
   end

   layout=menu('DISPLAY LAYOUT :',...
	       'Time-Frequency Representation',...
	       'TFR + Signal ',...
	       specstr,...
	       tfrsstr,...
	       colorbarstr,...
	       'Close');

   if (layout==3|layout==4),
    linlogspec=1-linlogspec;
   end
   if ((layout>=2 & layout<=4) & isempty(sig)),
    disp('Impossible action : the signal is unavailable');
   else
    access=2;
    linlog=linlogtfr+2*linlogspec;
    state=issig+2*iscolorbar;
    isgrid=isgridsig+2*isgridspe+4*isgridtfr;
    param = [display,linlog,threshold,levelnumb,Nf2,layout,access,state,fs,isgrid];
    map=colormap;
    if (nargin<=4),
     tfrview(tfr,sig,t,method,param,map);
    elseif (nargin==5),
     tfrview(tfr,sig,t,method,param,map,p1);
    elseif (nargin==6),
     tfrview(tfr,sig,t,method,param,map,p1,p2);
    elseif (nargin==7),
     tfrview(tfr,sig,t,method,param,map,p1,p2,p3);
    elseif (nargin==8),
     tfrview(tfr,sig,t,method,param,map,p1,p2,p3,p4);
    elseif (nargin==9),
     tfrview(tfr,sig,t,method,param,map,p1,p2,p3,p4,p5);
    end;

    axesh=get(gcf,'UserData');
    axcb=axesh(1); axsig=axesh(2); axspec=axesh(3); axtfr=axesh(4);

    if layout==1,			% Time-Frequency Representation
     axes(axsig);  cla reset; set(gca,'Visible','off');
     axes(axspec); cla reset; set(gca,'Visible','off');
     issig=0; isspec=0;
    elseif layout==2,			% TFR + Signal
     axes(axspec); cla reset; set(gca,'Visible','off');
     issig=1; isspec=0;
    elseif layout==3,			% TFR + spectrum
     axes(axsig);  cla reset; set(gca,'Visible','off');
     issig=0; isspec=1;
    elseif layout==4,			% TFR + signal + spectrum
      issig=1; isspec=1;
    elseif layout==5,			% Colorbar
     iscolorbar=1-iscolorbar;
    elseif ((layout==2|layout==3|layout==4) & isempty(sig)),
     disp('Unallowed action : the signal is anavailable.');
    end;

    lo(indlo)=layout;
    indlo=indlo+1;
   end
  end
  while (layout==6|layout==5),
   indlo=indlo-1;
   if indlo>0,
    layout=lo(indlo);
   else
    layout=layoutold;
   end
  end

 elseif (choice==3),			% Change the color map

  colmap=1;
  while colmap~=12,
   colmap=menu('COLOR MAP :',...
	       'hsv','jet','cool','bone','gray','hot','prism',...
	       'brighten','darken','permute','spin','Close');
   if colmap==1,
    colormap(hsv);
   elseif colmap==2,
    colormap(jet);
   elseif colmap==3,
    colormap(cool);
   elseif colmap==4,
    colormap(bone);
   elseif colmap==5,
    colormap(gray);
   elseif colmap==6,
    colormap(hot);
   elseif colmap==7,
    colormap(prism);
   elseif colmap==8,
    brighten(0.25);
   elseif colmap==9,
    brighten(-0.25);
   elseif colmap==10,
    c = colormap; colormap(flipud(c));
   elseif colmap==11,
    spinmap;
   end
  end

 elseif (choice==4), 			% Change the sampling frequency

  fprintf(' Old sampling frequency: %f',fs); fsold=fs;
  fs=input(' New sampling frequency: ');
  if isempty(fs), fs=fsold; end

 elseif (choice==5),			% Change the threshold

  fprintf(' Old threshold: %f', threshold); throld=threshold;
  threshold=input(' New threshold: ');
  if isempty(threshold), threshold=throld; end

 elseif (choice==6),			% Change the lin/log scale of tfr

  linlogtfr=1-linlogtfr;

 elseif (choice==7),			% Change the number of levels

  fprintf(' Old number of levels: %f',levelnumb); levelold=levelnumb;
  levelnumb=input(' New number of levels: ');
  if isempty(levelnumb), levelnumb=levelold; end

 elseif (choice==8),			% Grids

  if ~issig & ~isspec,			% No signal and no spectrum
   isgridtfr=1-isgridtfr; axes(axtfr); grid

  elseif issig & ~isspec,		% A signal, no spectrum
   Grid=1;
   while Grid~=3,
    if ~isgridsig,
     gridsigstr='Add a grid on the signal';
    else
     gridsigstr='Remove the grid on the signal';
    end
    if ~isgridtfr,
     gridtfrstr='Add a grid on the TFR';
    else
     gridtfrstr='Remove the grid on the TFR';
    end
    Grid=menu('GRID MENU :',gridsigstr,gridtfrstr,'Close');
    if Grid==1,
     isgridsig=1-isgridsig; axes(axsig); grid
    elseif Grid==2,
     isgridtfr=1-isgridtfr; axes(axtfr); grid
    end
   end

  elseif ~issig & isspec,		% No signal, a spectrum
   Grid=1;
   while Grid~=3,
    if ~isgridspe,
     gridspestr='Add a grid on the spectrum';
    else
     gridspestr='Remove the grid on the spectrum';
    end
    if ~isgridtfr,
     gridtfrstr='Add a grid on the TFR';
    else
     gridtfrstr='Remove the grid on the TFR';
    end
    Grid=menu('GRID MENU :',gridspestr,gridtfrstr,'Close');
    if Grid==1,
     isgridspe=1-isgridspe; axes(axspec); grid
    elseif Grid==2,
     isgridtfr=1-isgridtfr; axes(axtfr); grid
    end
   end

  else					% A signal and a spectrum
   Grid=1;
   while Grid~=4,
    if ~isgridsig,
     gridsigstr='Add a grid on the signal';
    else
     gridsigstr='Remove the grid on the signal';
    end
    if ~isgridspe,
     gridspestr='Add a grid on the spectrum';
    else
     gridspestr='Remove the grid on the spectrum';
    end
    if ~isgridtfr,
     gridtfrstr='Add a grid on the TFR';
    else
     gridtfrstr='Remove the grid on the TFR';
    end
    Grid=menu('GRID MENU :',gridsigstr,gridspestr,gridtfrstr,'Close');
    if Grid==1,
     isgridsig=1-isgridsig; axes(axsig); grid
    elseif Grid==2,
     isgridspe=1-isgridspe; axes(axspec); grid
    elseif Grid==3,
     isgridtfr=1-isgridtfr; axes(axtfr); grid
    end
   end
  end

 elseif (choice==9),			% Save the parameters

  f=freq*fs;
  Nmethod=length(method);
  if comp(1:2)=='PC',
   namedflt=[method(4:Nmethod),num2str(Nsig),'.mat'];
   [name,PathWorkDir] = uiputfile(namedflt, 'Save As');
  else
   namedflt=[method(4:Nmethod),num2str(Nsig)];
   nameStr=[' Name of the MAT file [',namedflt,'] : '];
   name=input(nameStr,'s');
   while (length(name)>8),
    disp(' The name must have less than 8 characters');
    name=input(nameStr,'s');
   end
   if isempty(name),
    name=namedflt;
   end
  end
  access=0;
  linlog=linlogtfr+2*linlogspec;
  state=issig+2*iscolorbar;
  isgrid=isgridsig+2*isgridspe+4*isgridtfr;
  param = [display,linlog,threshold,levelnumb,Nf2,layout,access,state,fs,isgrid];
  map=colormap;
  if (nargin<=4),
   TfrQView=['tfrqview(tfr,sig,t,method)'];
   TfrView =['clf;tfrview(tfr,sig,t,method,param,map)'];
   eval(['save ',PathWorkDir,name,...
' tfr sig t f fs method param map TfrView TfrQView']);
  elseif (nargin==5),
   TfrQView=['tfrqview(tfr,sig,t,method,p1)'];
   TfrView =['clf; tfrview(tfr,sig,t,method,param,map,p1)'];
   eval(['save ',PathWorkDir,name,...
' tfr sig t f fs method param map p1 TfrView TfrQView']);
  elseif (nargin==6),
   TfrQView=['tfrqview(tfr,sig,t,method,p1,p2)'];
   TfrView =['clf; tfrview(tfr,sig,t,method,param,map,p1,p2)'];
   eval(['save ',PathWorkDir,name,...
' tfr sig t f fs method param map p1 p2 TfrView TfrQView']);
  elseif (nargin==7),
   TfrQView=['tfrqview(tfr,sig,t,method,p1,p2,p3)'];
   TfrView =['clf; tfrview(tfr,sig,t,method,param,map,p1,p2,p3)'];
   eval(['save ',PathWorkDir,name,...
' tfr sig t f fs method param map p1 p2 p3 TfrView TfrQView']);
  elseif (nargin==8),
   TfrQView=['tfrqview(tfr,sig,t,method,p1,p2,p3,p4)'];
   TfrView =['clf; tfrview(tfr,sig,t,method,param,map,p1,p2,p3,p4)'];
   eval(['save ',PathWorkDir,name,...
' tfr sig t f fs method param map p1 p2 p3 p4 TfrView TfrQView']);
  elseif (nargin==9),
   TfrQView=['tfrqview(tfr,sig,t,method,p1,p2,p3,p4,p5)'];
   TfrView =['clf; tfrview(tfr,sig,t,method,param,map,p1,p2,p3,p4,p5)'];
   eval(['save ',PathWorkDir,name,...
' tfr sig t f fs method param map p1 p2 p3 p4 p5 TfrView TfrQView']);
  end;
  disp(' ');
  SaveTxt1=[' The file is saved in the directory ',PathWorkDir];
  SaveTxt2=['  under the name ',name,'.mat'];
  disp(SaveTxt1); disp(SaveTxt2);

  disp(' If you want to find again the exact layout of this screen, do');
  Txt1=['	load ',PathWorkDir,name,'; eval(TfrView);'];
  disp(Txt1);
  disp(' If you want to restart the display session under tfrqview, do');
  Txt2=['	load ',PathWorkDir,name,'; eval(TfrQView);'];
  disp(Txt2);

 elseif (choice==10),			% Save options

  save options fs threshold linlogtfr linlogspec levelnumb colmap ...
       display layout iscolorbar isgridsig ...
       isgridspe isgridtfr issig isspec;
  disp(' '); disp(' Options saved');

 elseif (choice==11),			% Print the current figure

  Nmethod=length(method);
  if comp(1:2)=='PC',
   namedflt=[method(4:Nmethod),num2str(Nsig),'.eps'];
   [name,PathWorkDir] = uiputfile(namedflt, 'Save As');
  else
   namedflt=[method(4:Nmethod),num2str(Nsig)];
   nameStr=[' Name of the EPS file [',namedflt,'] : '];
   name=input(nameStr,'s');
   while (length(name)>8),
    disp('The name must have less than 8 characters');
    name=input(nameStr,'s');
   end
   if isempty(name),
    name=namedflt;
   end
  end
  eval(['print -deps ',PathWorkDir,name]); disp(' ');
  PrintTxt1=[' The file is saved in the directory ',PathWorkDir];
  if comp(1:2)=='PC',
   PrintTxt2=['  under the name ',name];
  else
   PrintTxt2=['  under the name ',name,'.eps'];
  end
  disp(PrintTxt1); disp(PrintTxt2);

 end;

 if display~=7,
  displayold=display;
 end

end

if (comp(1:2)~='PC' & exist('workdir.mat')),
 !rm workdir.mat
end

disp(' ');


function h = contour(sF,varargin)
% spherical contour plot
%
% Syntax
%   contour(v,data)
%
% Input
%   sF - @S2Fun
%
% Options
%   contours - number of contours
%
% See also
%   S2Fun/plot S2Fun/contourf
%

% plot the function values
h = plot(sF,'contour',varargin{:});

% remove output if not required
if nargout == 0, clear h; end

end


function [p1,p2,P1_l,P2_l] = idpLin2idpPnts(l)

% IDPLIN2IDPPNTS  IDP line to two IDP points conversion.
%   [P1,P2] = IDPLIN2IDPPNTS(L) extracts the two endpoints of the IDP line
%   L in the form of two IDP points with the same anchor of that of the
%   line.
%
%   [p1,p2,P1_l,P2_l] = IDPLIN2IDPPNTS(...) returns the Jacobians wrt L.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

p1 = l(1:6,:);
p2 = l([1:3 7:9],:);

if nargout > 2

    P1_l = [eye(6) zeros(6,3)];
    P2_l = [eye(3) zeros(3,6) ; zeros(3,6) eye(3)];

end

return

%% jac

syms x y z p1 y1 r1 p2 y2 r2 real
l = [x y z p1 y1 r1 p2 y2 r2]';

[p1,p2,P1_l,P2_l] = idpLin2idpPnts(l);

simplify(P1_l - jacobian(p1,l))
simplify(P2_l - jacobian(p2,l))

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB 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.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE