123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933 |
- function varargout = spm_FcUtil(varargin)
- % Contrast utilities
- % FORMAT varargout = spm_FcUtil(action,varargin)
- %_______________________________________________________________________
- %
- % spm_FcUtil is a multi-function function containing various utilities
- % for contrast construction and manipulation. In general, it accepts
- % design matrices as plain matrices or as space structures setup by
- % spm_sp (that is preferable in general).
- %
- % The use of spm_FcUtil should help with robustness issues and
- % maintainability of SPM. % 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.
- %
- %
- % ======================================================================
- % case 'fconfields' %- fields of F contrast
- % Fc = spm_FcUtil('FconFields')
- %
- %- simply returns the fields of a contrast structure.
- %
- %=======================================================================
- % case 'set' %- Create an F contrast
- % Fc = spm_FcUtil('Set',name, STAT, set_action, value, sX)
- %
- %- Set will fill in the contrast structure, in particular
- %- c (in the contrast space), X1o (the space actually tested) and
- %- X0 (the space left untested), such that space([X1o X0]) == sX.
- %- STAT is either 'F' or 'T';
- %- name is a string descibing the contrast.
- %
- %- There are three ways to set a contrast :
- %- set_action is 'c','c+' : value can then be zeros.
- %- dimensions are in X',
- %- f c+ is used, value is projected onto sX';
- %- iX0 is set to 'c' or 'c+';
- %- set_action is 'iX0' : defines the indices of the columns
- %- that will not be tested. Can be empty.
- %- set_action is 'X0' : defines the space that will remain
- %- unchanged. The orthogonal complement is
- %- tested; iX0 is set to 'X0';
- %-
- %=======================================================================
- % case 'isfcon' %- Is it an F contrast ?
- % b = spm_FcUtil('IsFcon',Fc)
- %
- %=======================================================================
- % case 'fconedf' %- F contrast edf
- % [edf_tsp edf_Xsp] = spm_FcUtil('FconEdf', Fc, sX [, V])
- %
- %- compute the effective degrees of freedom of the numerator edf_tsp
- %- and (optionally) the denominator edf_Xsp of the contrast.
- %
- %=======================================================================
- % case 'hsqr' %-Extra sum of squares sqr matrix for beta's from contrast
- % hsqr = spm_FcUtil('Hsqr',Fc, sX)
- %
- %- This computes the matrix hsqr such that a the numerator of an F test
- %- will be beta'*hsqr'*hsqr*beta
- %
- %=======================================================================
- % case 'h' %-Extra sum of squares matrix for beta's from contrast
- % H = spm_FcUtil('H',Fc, sX)
- %
- %- This computes the matrix H such that a the numerator of an F test
- %- will be beta'*H*beta
- %-
- %=======================================================================
- % case 'yc' %- Fitted data corrected for confounds defined by Fc
- % Yc = spm_FcUtil('Yc',Fc, sX, b)
- %
- %- Input : b : the betas
- %- Returns the corrected data Yc for given contrast. Y = Yc + Y0 + error
- %
- %=======================================================================
- % case 'y0' %- Confounds data defined by Fc
- % Y0 = spm_FcUtil('Y0',Fc, sX, b)
- %
- %- Input : b : the betas
- %- Returns the confound data Y0 for a given contrast. Y = Yc + Y0 + error
- %
- %=======================================================================
- % case {'|_'} %- Fc orthogonalisation
- % Fc = spm_FcUtil('|_',Fc1, sX, Fc2)
- %
- %- Orthogonolise a (list of) contrasts Fc1 wrt a (list of) contrast Fc2
- %- such that the space these contrasts test are orthogonal.
- %- If contrasts are not estimable contrasts, works with the estimable
- %- part. In any case, returns estimable contrasts.
- %
- %=======================================================================
- % case {'|_?'} %- Are contrasts orthogonals
- % b = spm_FcUtil('|_?',Fc1, sX [, Fc2])
- %
- %- Tests whether a (list of) contrast is orthogonal. Works with the
- %- estimable part if they are not estimable. With only one argument,
- %- tests whether the list is made of orthogonal contrasts. With Fc2
- %- provided, tests whether the two (list of) contrast are orthogonal.
- %
- %=======================================================================
- % case 'in' %- Fc1 is in list of contrasts Fc2
- % [iFc2 iFc1] = spm_FcUtil('In', Fc1, sX, Fc2)
- %
- %- Tests wether a (list of) contrast Fc1 is in a list of contrast Fc2.
- %- returns the indices iFc2 where element of Fc1 have been found
- %- in Fc2 and the indices iFc1 of the element of Fc1 found in Fc2.
- %- These indices are not necessarily unique.
- %
- %=======================================================================
- % case '~unique' %- Fc list unique
- % idx = spm_FcUtil('~unique', Fc, sX)
- %
- %- returns indices ofredundant contrasts in Fc
- %- such that Fc(idx) = [] makes Fc unique.
- %
- %=======================================================================
- % case {'0|[]','[]|0'} %- Fc is null or empty
- % b = spm_FcUtil('0|[]', Fc, sX)
- %
- %- NB : for the "null" part, checks if the contrast is in the null space
- %- of sX (completely non estimable !)
- %=======================================================================
- %
- %_______________________________________________________________________
- % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
- % Jean-Baptiste Poline
- % $Id: spm_FcUtil.m 5219 2013-01-29 17:07:07Z spm $
- %-Format arguments
- %-----------------------------------------------------------------------
- if nargin==0, error('do what? no arguments given...')
- else action = varargin{1}; end
- switch lower(action),
- case 'fconfields' %- fields of F contrast
- %=======================================================================
- % Fc = spm_FcUtil('FconFields')
- if nargout > 1, error('Too many output arguments: FconFields'), end
- if nargin > 1, error('Too many input arguments: FconFields'), end
- varargout = {sf_FconFields};
- case {'set','v1set'} %- Create an F contrast
- %=======================================================================
- % Fc = spm_FcUtil('Set',name, STAT, set_action, value, sX)
- %
- % Sets the contrast structure with set_action either 'c', 'X0' or 'iX0'
- % resp. for a contrast, the null hyp. space or the indices of which.
- % STAT can be 'T' or 'F'.
- %
- % If not set by iX0 (in which case field .iX0 containes the indices),
- % field .iX0 is set as a string containing the set_action: {'X0','c','c+','ukX0'}
- %
- % if STAT is T, then set_action should be 'c' or 'c+'
- % (at the moment, just a warning...)
- % if STAT is T and set_action is 'c' or 'c+', then
- % checks whether it is a real T.
- %
- % 'v1set' is NOT provided for backward compatibility so far ...
- %-check # arguments...
- %--------------------------------------------------------------------------
- if nargin<6, error('insufficient arguments'), end
- if nargout > 1, error('Too many output arguments Set'), end
- %-check arguments...
- %--------------------------------------------------------------------------
- if ~ischar(varargin{2}), error('~ischar(name)'), end
- if ~(varargin{3}=='F'||varargin{3}=='T'||varargin{3}=='P'),
- error('~(STAT==F|STAT==T|STAT==P)'), end
- if ~ischar(varargin{4}), error('~ischar(varargin{4})');
- else set_action = varargin{4}; end
- sX = varargin{6};
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end
- if isempty(sX.X), error('Empty space X in Set'); end
- Fc = sf_FconFields;
- %- use the name as a flag to insure that F-contrast has been
- %- properly created;
- Fc.name = varargin{2};
- Fc.STAT = varargin{3};
- if Fc.STAT=='T' && ~(any(strcmp(set_action,{'c+','c'})))
- warning('enter T stat with contrast - here no check rank == 1');
- end
- [sC,sL] = spm_sp('size',sX);
- %- allow to define the contrast the old (version 1) way ?
- %- NO. v1 = strcmp(action,'v1set');
- switch set_action,
- case {'c','c+'}
- Fc.iX0 = set_action;
- c = spm_sp(':', sX, varargin{5});
- if isempty(c)
- [Fc.X1o.ukX1o,Fc.X0.ukX0] = spm_SpUtil('+c->Tsp',sX,[]);
- %- v1 [Fc.X1o Fc.X0] = spm_SpUtil('c->Tsp',sX,[]);
- Fc.c = c;
- elseif size(c,1) ~= sL,
- error(['not contrast dim. in ' mfilename ' ' set_action]);
- else
- if strcmp(set_action,'c+')
- if ~spm_sp('isinspp',sX,c), c = spm_sp('oPp:',sX,c); end
- end;
- if Fc.STAT=='T' && ~sf_is_T(sX,c)
- %- Could be make more self-correcting by giving back an F
- error('trying to define a t that looks like an F');
- end
- Fc.c = c;
- [Fc.X1o.ukX1o,Fc.X0.ukX0] = spm_SpUtil('+c->Tsp',sX,c);
- %- v1 [Fc.X1o Fc.X0] = spm_SpUtil('c->Tsp',sX,c);
- end
- %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- % 'option given for completeness - not for SPM use'
- case {'X0'}
- warning('option given for completeness - not for SPM use');
- Fc.iX0 = set_action;
- X0 = spm_sp(':', sX, varargin{5});
- if isempty(X0),
- Fc.c = spm_sp('xpx',sX);
- Fc.X1o.ukX1o = spm_sp('cukx',sX);
- Fc.X0.ukX0 = [];
- elseif size(X0,1) ~= sC,
- error('dimension of X0 wrong in Set');
- else
- Fc.c = spm_SpUtil('X0->c',sX,X0);
- Fc.X0.ukX0 = spm_sp('ox',sX)'*X0;
- Fc.X1o.ukX1o = spm_SpUtil('+c->Tsp',sX,Fc.c);
- end
-
- case 'ukX0'
- warning('option given for completeness - not for SPM use');
- Fc.iX0 = set_action;
- if isempty(ukX0),
- Fc.c = spm_sp('xpx',sX);
- Fc.X1o.ukX1o = spm_sp('cukx',sX);
- Fc.X0.ukX0 = [];
- elseif size(ukX0,1) ~= spm_sp('rk',sX),
- error('dimension of cukX0 wrong in Set');
- else
- Fc.c = spm_SpUtil('+X0->c',sX,ukX0);
- Fc.X0.ukX0 = ukX0;
- Fc.X1o.ukX1o = spm_SpUtil('+c->Tsp',sX,Fc.c);
- end
- %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- case 'iX0'
- iX0 = varargin{5};
- iX0 = spm_SpUtil('iX0check',iX0,sL);
- Fc.iX0 = iX0;
- Fc.X0.ukX0 = spm_sp('ox',sX)' * spm_sp('Xi',sX,iX0);
- if isempty(iX0),
- Fc.c = spm_sp('xpx',sX);
- Fc.X1o.ukX1o = spm_sp('cukx',sX);
- else
- Fc.c = spm_SpUtil('i0->c',sX,iX0);
- Fc.X1o.ukX1o = spm_SpUtil('+c->Tsp',sX,Fc.c);
- end
-
- otherwise
- error('wrong action in Set ');
-
- end
- varargout = {Fc};
- case 'x0' % spm_FcUtil('X0',Fc,sX)
- %=======================================================================
- if nargin ~= 3,
- error('too few/many input arguments - need 2');
- else
- Fc = varargin{2}; sX = varargin{3};
- end
- if nargout ~= 1, error('too few/many output arguments - need 1'), end
- if ~sf_IsFcon(Fc), error('argument is not a contrast struct'), end
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end
- varargout = {sf_X0(Fc,sX)};
- case 'x1o' % spm_FcUtil('X1o',Fc,sX)
- %=======================================================================
- if nargin ~= 3,
- error('too few/many input arguments - need 2');
- else
- Fc = varargin{2}; sX = varargin{3};
- end
- if nargout ~= 1, error('too few/many output arguments - need 1'), end
- if ~sf_IsFcon(Fc), error('argument is not a contrast struct'), end
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end
- varargout = {sf_X1o(Fc,sX)};
- case 'isfcon' %- Is it an F contrast ?
- %=======================================================================
- % yes_no = spm_FcUtil('IsFcon',Fc)
- if nargin~=2, error('too few/many input arguments - need 2'), end
- if ~isstruct(varargin{2}), varargout={0};
- else varargout = {sf_IsFcon(varargin{2})};
- end
- case 'fconedf' %- F contrast edf
- %=======================================================================
- % [edf_tsp edf_Xsp] = spm_FcUtil('FconEdf', Fc, sX [, V])
- if nargin<3, error('Insufficient arguments'), end
- if nargout >= 3, error('Too many output argument.'), end
- Fc = varargin{2};
- sX = varargin{3};
- if nargin == 4, V = varargin{4}; else V = []; end
- if ~sf_IsFcon(Fc), error('Fc must be Fcon'), end
- if ~spm_sp('isspc',sX)
- sX = spm_sp('set',sX); end
- if ~sf_isempty_X1o(Fc)
- [trMV, trMVMV] = spm_SpUtil('trMV',sf_X1o(Fc,sX),V);
- else
- trMV = 0;
- trMVMV = 0;
- end
- if ~trMVMV, edf_tsp = 0; warning('edf_tsp = 0'),
- else edf_tsp = trMV^2/trMVMV; end;
- if nargout == 2
- [trRV, trRVRV] = spm_SpUtil('trRV',sX,V);
- if ~trRVRV, edf_Xsp = 0; warning('edf_Xsp = 0'),
- else edf_Xsp = trRV^2/trRVRV; end;
- varargout = {edf_tsp, edf_Xsp};
- else
- varargout = {edf_tsp};
- end
- %=======================================================================
- %=======================================================================
- % parts that use F contrast
- %=======================================================================
- %=======================================================================
- %
- % Quick reference : L : can be lists of ...
- %-------------------------
- % ('Hsqr',Fc, sX) : Out: Hsqr / ESS = b' * Hsqr' * Hsqr * b
- % ('H',Fc, sX) : Out: H / ESS = b' * H * b
- % ('Yc',Fc, sX, b) : Out: Y corrected = X*b - X0*X0- *Y
- % ('Y0',Fc, sX, b) : Out: Y0 = X0*X0- *Y
- % ('|_',LFc1, sX, LFc2) : Out: Fc1 orthog. wrt Fc2
- % ('|_?',LFc1,sX [,LFc2]): Out: is Fc2 ortho to Fc1 or is Fc1 ortho ?
- % ('In', LFc1, sX, LFc2) : Out: indices of Fc2 if "in", 0 otherwise
- % ('~unique', LFc, sX) : Out: indices of redundant contrasts
- % ('0|[]', Fc, sX) : Out: 1 if Fc is zero or empty, 0 otherwise
- case 'hsqr' %-Extra sum of squares matrix for beta's from contrast
- %=======================================================================
- % hsqr = spm_FcUtil('Hsqr',Fc, sX)
- if nargin<3, error('Insufficient arguments'), end
- if nargout>1, error('Too many output argument.'), end
- Fc = varargin{2};
- sX = varargin{3};
- if ~sf_IsFcon(Fc), error('Fc must be F-contrast'), end
- if ~sf_IsSet(Fc), error('Fcon must be set'); end; %-
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- if sf_isempty_X1o(Fc)
- if ~sf_isempty_X0(Fc)
- %- assumes that X0 is sX.X
- %- warning(' Empty X1o in spm_FcUtil(''Hsqr'',Fc,sX) ');
- varargout = { zeros(1,spm_sp('size',sX,2)) };
- else
- error(' Fc must be set ');
- end
- else
- varargout = { sf_Hsqr(Fc,sX) };
- end
- case 'h' %-Extra sum of squares matrix for beta's from contrast
- %=======================================================================
- % H = spm_FcUtil('H',Fc, sX)
- % Empty and zeros dealing :
- % This routine never returns an empty matrix.
- % If sf_isempty_X1o(Fc) | isempty(Fc.c) it explicitly
- % returns a zeros projection matrix.
- if nargin<2, error('Insufficient arguments'), end
- if nargout>1, error('Too many output argument.'), end
- Fc = varargin{2};
- sX = varargin{3};
- if ~sf_IsFcon(Fc), error('Fc must be F-contrast'), end
- if ~sf_IsSet(Fc), error('Fcon must be set'); end; %-
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- if sf_isempty_X1o(Fc)
- if ~sf_isempty_X0(Fc)
- %- assumes that X0 is sX.X
- %- warning(' Empty X1o in spm_FcUtil(''H'',Fc,sX) ');
- varargout = { zeros(spm_sp('size',sX,2)) };
- else
- error(' Fc must be set ');
- end
- else
- varargout = { sf_H(Fc,sX) };
- end
- case 'yc' %- Fitted data corrected for confounds defined by Fc
- %=======================================================================
- % Yc = spm_FcUtil('Yc',Fc, sX, b)
- if nargin < 4, error('Insufficient arguments'), end
- if nargout > 1, error('Too many output argument.'), end
- Fc = varargin{2}; sX = varargin{3}; b = varargin{4};
- if ~sf_IsFcon(Fc), error('Fc must be F-contrast'), end
- if ~sf_IsSet(Fc), error('Fcon must be set'); end;
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- % if ~spm_FcUtil('Rcompatible',Fc,sX), ...
- % error('sX and Fc must be compatible'), end;
- if spm_sp('size',sX,2) ~= size(b,1),
- error('sX and b must be compatible'), end;
- if sf_isempty_X1o(Fc)
- if ~sf_isempty_X0(Fc)
- %- if space of interest empty or null, returns zeros !
- varargout = { zeros(spm_sp('size',sX,1),size(b,2)) };
- else
- error(' Fc must be set ');
- end
- else
- varargout = { sf_Yc(Fc,sX,b) };
- end
- case 'y0' %- Fitted data corrected for confounds defined by Fc
- %=======================================================================
- % Y0 = spm_FcUtil('Y0',Fc, sX, b)
- if nargin < 4, error('Insufficient arguments'), end
- if nargout > 1, error('Too many output argument.'), end
- Fc = varargin{2}; sX = varargin{3}; b = varargin{4};
- if ~sf_IsFcon(Fc), error('Fc must be F-contrast'), end
- if ~sf_IsSet(Fc), error('Fcon must be set'); end;
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- if spm_sp('size',sX,2) ~= size(b,1),
- error('sX and b must be compatible'), end;
- if sf_isempty_X1o(Fc)
- if ~sf_isempty_X0(Fc)
- %- if space of interest empty or null, returns zeros !
- varargout = { sX.X*b };
- else
- error(' Fc must be set ');
- end
- else
- varargout = { sf_Y0(Fc,sX,b) };
- end
- case {'|_'} %- Fc orthogonalisation
- %=======================================================================
- % Fc = spm_FcUtil('|_',Fc1, sX, Fc2)
- % returns Fc1 orthogonolised wrt Fc2
- if nargin < 4, error('Insufficient arguments'), end
- if nargout > 1, error('Too many output argument.'), end
- Fc1 = varargin{2}; sX = varargin{3}; Fc2 = varargin{4};
- %-check arguments
- %-----------------------------------------------------------------------
- L1 = length(Fc1);
- if ~L1, warning('no contrast given to |_'); varargout = {[]}; return; end
- for i=1:L1
- if ~sf_IsFcon(Fc1(i)), error('Fc1(i) must be a contrast'), end
- end
- L2 = length(Fc2);
- if ~L2, error('must have at least a contrast in Fc2'); end
- for i=1:L2
- if ~sf_IsFcon(Fc2(i)), error('Fc2(i) must be a contrast'), end
- end
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- %-create an F-contrast for all the Fc2
- %--------------------------------------------------------------------------
- str = Fc2(1).name; for i=2:L2, str = [str ' ' Fc2(i).name]; end;
- Fc2 = spm_FcUtil('Set',str,'F','c+',cat(2,Fc2(:).c),sX);
- if sf_isempty_X1o(Fc2) || sf_isnull(Fc2,sX)
- varargout = {Fc1};
- else
- for i=1:L1
- if sf_isempty_X1o(Fc1(i)) || sf_isnull(Fc1(i),sX)
- %- Fc1(i) is an [] or 0 contrast : ortho to anything;
- out(i) = Fc1(i);
- else
- out(i) = sf_fcortho(Fc1(i), sX, Fc2);
- end
- end
- varargout = {out};
- end
- case {'|_?'} %- Are contrasts orthogonals
- %=======================================================================
- % b = spm_FcUtil('|_?',Fc1, sX [, Fc2])
- if nargin < 3, error('Insufficient arguments'), end
- Fc1 = varargin{2}; sX = varargin{3};
- if nargin > 3, Fc2 = varargin{4}; else Fc2 = []; end;
- if isempty(Fc1), error('give at least one non empty contrast'), end;
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- for i=1:length(Fc1)
- if ~sf_IsFcon(Fc1(i)), error('Fc1(i) must be a contrast'), end
- end
- for i=1:length(Fc2)
- if ~sf_IsFcon(Fc2(i)), error('Fc2(i) must be a contrast'), end
- end
- varargout = { sf_Rortho(Fc1,sX,Fc2) };
- case 'in' %- Fc1 is in list of contrasts Fc2
- %=======================================================================
- % [iFc2 iFc1] = spm_FcUtil('In', Fc1, sX, Fc2)
- % returns indice of Fc2 if "in", 0 otherwise
- % NB : If T- stat, the routine checks whether Fc.c is of
- % size one. This is ensure if contrast is set
- % or manipulated (ortho ..) with spm_FcUtil
- % note that the algorithmn works \emph{only because} Fc2(?).c
- % and Fc1.c are in space(X')
- if nargin < 4, error('Insufficient arguments'), end
- if nargout > 2, error('Too many output argument.'), end
- Fc1 = varargin{2}; Fc2 = varargin{4}; sX = varargin{3};
- L1 = length(Fc1);
- if ~L1, warning('no contrast given to in');
- if nargout == 2, varargout = {[] []};
- else varargout = {[]}; end;
- return;
- end
- for i=1:L1
- if ~sf_IsFcon(Fc1(i)), error('Fc1(i) must be a contrast'), end
- end
- L2 = length(Fc2);
- if ~L2, error('must have at least a contrast in Fc2'); end
- for i=1:L2
- if ~sf_IsFcon(Fc2(i)), error('Fc2(i) must be F-contrast'), end
- end
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- [idxFc2,idxFc1] = sf_in(Fc1, sX, Fc2);
- if isempty(idxFc2), idxFc2 = 0; end
- if isempty(idxFc1), idxFc1 = 0; end
- switch nargout
- case {0,1}
- varargout = { idxFc2 };
- case 2
- varargout = { idxFc2 idxFc1 };
- otherwise
- error('Too many or not enough output arguments');
- end
- case '~unique' %- Fc list unique
- %=======================================================================
- % idx = spm_FcUtil('~unique', Fc, sX)
- %- returns indices of redundant contrasts in Fc
- %- such that Fc(idx) = [] makes Fc unique.
- %- if already unique returns []
- if nargin ~= 3, error('Insufficient/too many arguments'), end
- Fc = varargin{2}; sX = varargin{3};
- %----------------------------
- L1 = length(Fc);
- if ~L1, warning('no contrast given '); varargout = {[]}; return; end
- for i=1:L1
- if ~sf_IsFcon(Fc(i)), error('Fc(i) must be a contrast'), end
- end
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- %----------------------------
- varargout = { unique(sf_notunique(Fc, sX))};
- case {'0|[]','[]|0'} %- Fc is null or empty
- %=======================================================================
- % b = spm_FcUtil('0|[]', Fc, sX)
- % returns 1 if F-contrast is empty or null; assumes the contrast is set.
- if nargin ~= 3, error('Insufficient/too many arguments'), end
- Fc = varargin{2}; sX = varargin{3};
- %----------------------------
- L1 = length(Fc);
- if ~L1, warning('no contrast given to |_'); varargout = {[]}; return; end
- for i=1:L1
- if ~sf_IsFcon(Fc(i)), error('Fc(i) must be a contrast'), end
- end
- if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end;
- %----------------------------
- idx = [];
- for i=1:L1
- if sf_isempty_X1o(Fc(i)) || sf_isnull(Fc(i),sX), idx = [idx i]; end
- end
- if isempty(idx)
- varargout = {0};
- else
- varargout = {idx};
- end
- %=======================================================================
- otherwise
- %=======================================================================
- error('Unknown action string in spm_FcUtil')
- end; %---- switch lower(action),
- %=======================================================================
- %=======================================================================
- % Sub Functions
- %=======================================================================
- %=======================================================================
- %=======================================================================
- % Fcon = spm_FcUtil('FconFields')
- function Fc = sf_FconFields
- Fc = struct(...
- 'name', '',...
- 'STAT', '',...
- 'c', [],...
- 'X0', struct('ukX0',[]),...
- 'iX0', [],...
- 'X1o', struct('ukX1o',[]),...
- 'eidf', [],...
- 'Vcon', [],...
- 'Vspm', []);
-
- %=======================================================================
- % used internally. Minimum contrast structure
- function minFc = sf_MinFcFields
- minFc = struct(...
- 'name', '',...
- 'STAT', '',...
- 'c', [],...
- 'X0', [],...
- 'X1o', []);
- %=======================================================================
- % yes_no = spm_FcUtil('IsFcon',Fc)
- function b = sf_IsFcon(Fc)
- %- check that minimum fields of a contrast are in Fc
- b = 1;
- minnames = fieldnames(sf_MinFcFields);
- FCnames = fieldnames(Fc);
- for str = minnames'
- b = b & any(strcmp(str,FCnames));
- if ~b, break, end
- end
- %=======================================================================
- % used internally; To be set, a contrast structure should have
- % either X1o or X0 non empty. X1o can be non empty because c
- % is non empty.
- function b = sf_IsSet(Fc)
- b = ~sf_isempty_X0(Fc) | ~sf_isempty_X1o(Fc);
- %=======================================================================
- % used internally
- %
- function v = sf_ver(Fc)
- if isstruct(Fc.X0), v = 2; else v = 1; end
- %=======================================================================
- % used internally
- function b = sf_isempty_X1o(Fc)
- if sf_ver(Fc) > 1,
- b = isempty(Fc.X1o.ukX1o);
- %- consistency check
- if b ~= isempty(Fc.c),
- Fc.c, Fc.X1o.ukX1o, error('Contrast internally not consistent');
- end
- else
- b = isempty(Fc.X1o);
- %- consistency check
- if b ~= isempty(Fc.c),
- Fc.c, Fc.X1o, error('Contrast internally not consistent');
- end
- end
- %=======================================================================
- % used internally
- function b = sf_X1o(Fc,sX)
- if sf_ver(Fc) > 1,
- b = spm_sp('ox',sX)*Fc.X1o.ukX1o;
- else
- b = Fc.X1o;
- end
- %=======================================================================
- % used internally
- function b = sf_X0(Fc,sX)
- if sf_ver(Fc) > 1,
- b = spm_sp('ox',sX)*Fc.X0.ukX0;
- else
- b = Fc.X0;
- end
- %=======================================================================
- % used internally
- function b = sf_isempty_X0(Fc)
- if sf_ver(Fc) > 1,
- b = isempty(Fc.X0.ukX0);
- else
- b = isempty(Fc.X0);
- end
- %=======================================================================
- % Hsqr = spm_Fcutil('Hsqr',Fc,sX)
- function hsqr = sf_Hsqr(Fc,sX)
- %
- % Notations : H equiv to X1o, H = uk*a1, X = uk*ax, r = rk(sX),
- % sX.X is (n,p), H is (n,q), a1 is (r,q), ax is (r,p)
- % oxa1 is an orthonormal basis for a1, oxa1 is (r,qo<=q)
- % Algorithm :
- % v1 : Y'*H*(H'*H)-*H'*Y = b'*X'*H*(H'*H)-*H'*X*b
- % = b'*X'*oxH*oxH'*X*b
- % so hsrq is set to oxH'*X, a (q,n)*(n,p) op. + computation of oxH
- % v2 : X'*H*(H'*H)-*H'*X = ax'*uk'*uk*a1*(a1'*uk'*uk*a1)-*a1'*uk'*uk*ax
- % = ax'*a1*(a1'*a1)-*a1'*ax
- % = ax'*oxa1*oxa1'*ax
- %
- % so hsrq is set to oxa1'*ax : a (qo,r)*(r,p) operation! -:))
- % + computation of oxa1.
- %-**** fprintf('v%d\n',sf_ver(Fc));
- if sf_ver(Fc) > 1,
- hsqr = spm_sp('ox',spm_sp('set',Fc.X1o.ukX1o))' * spm_sp('cukx',sX);
- else
- hsqr = spm_sp('ox',spm_sp('set',Fc.X1o))'*spm_sp('x',sX);
- end
- %=======================================================================
- % H = spm_FcUtil('H',Fc)
- function H = sf_H(Fc,sX)
- %
- % Notations : H equiv to X1o, H = uk*a1, X = uk*ax
- % Algorithm :
- % v1 : Y'*H*(H'*H)-*H'*Y = b'*X'*H*(H'*H)-*H'*X*b
- % = b'*c*(H'*H)-*c'*b
- % = b'*c*(c'*(X'*X)-*c)-*c'*b
- %- v1 : Note that pinv(Fc.X1o' * Fc.X1o) is not too bad
- %- because dimensions are only (q,q). See sf_hsqr for notations.
- %- Fc.c and Fc.X1o should match. This is ensure by using FcUtil.
- %-**** fprintf('v%d\n',sf_ver(Fc));
- if sf_ver(Fc) > 1,
- hsqr = sf_Hsqr(Fc,sX);
- H = hsqr' * hsqr;
- else
- H = Fc.c * pinv(Fc.X1o' * Fc.X1o) * Fc.c';
- % H = {c*spm_sp('x-',spm_sp('Set',c'*spm_sp('xpx-',sX)*c) )*c'}
- end
- %=======================================================================
- % Yc = spm_FcUtil('Yc',Fc,sX,b)
- function Yc = sf_Yc(Fc,sX,b)
- Yc = sX.X*spm_sp('xpx-',sX)*sf_H(Fc,sX)*b;
- %=======================================================================
- % Y0 = spm_FcUtil('Y0',Fc,sX,b)
- function Y0 = sf_Y0(Fc,sX,b)
- Y0 = sX.X*(eye(spm_sp('size',sX,2)) - spm_sp('xpx-',sX)*sf_H(Fc,sX))*b;
- %=======================================================================
- % Fc = spm_FcUtil('|_',Fc1, sX, Fc2)
- function Fc1o = sf_fcortho(Fc1, sX, Fc2)
- %--- use the space facility to ensure the proper tolerance dealing...
- c1_2 = Fc1.c - sf_H(Fc2,sX)*spm_sp('xpx-:',sX,Fc1.c);
- Fc1o = spm_FcUtil('Set',['(' Fc1.name ' |_ (' Fc2.name '))'], ...
- Fc1.STAT, 'c+',c1_2,sX);
- %- In the large (scans) dimension :
- %- c = sX.X'*spm_sp('r:',spm_sp('set',Fc2.X1o),Fc1.X1o);
- %- Fc1o = spm_FcUtil('Set',['(' Fc1.name ' |_ (' Fc2.name '))'], ...
- %- Fc1.STAT, 'c',c,sX);
- %=======================================================================
- function b = sf_Rortho(Fc1,sX,Fc2)
- if isempty(Fc2)
- if length(Fc1) <= 1, b = 0;
- else
- c1 = cat(2,Fc1(:).c);
- b = ~any(any( abs(triu(c1'*spm_sp('xpx-:',sX,c1), 1)) > sX.tol));
- end
- else
- c1 = cat(2,Fc1(:).c); c2 = cat(2,Fc2(:).c);
- b = ~any(any( abs(c1'*spm_sp('xpx-:',sX,c2)) > sX.tol ));
- end
- %=======================================================================
- % b = spm_FcUtil('0|[]', Fc, sX)
- %- returns 1 if F-contrast is empty or null; assumes the contrast is set.
- %- Assumes that if Fc.c contains only zeros, so does Fc.X1o.
- %- this is ensured if spm_FcUtil is used
- function boul = sf_isnull(Fc,sX)
- %
- boul = ~any(any(spm_sp('oPp:',sX,Fc.c)));
- %=======================================================================
- % Fc = spm_FcUtil('Set',name, STAT, set_action, value, sX)
- function boul = sf_is_T(sX,c)
- %- assumes that the dimensions are OK
- %- assumes c is not empty
- %- Does NOT assumes that c is space of sX'
- %- A rank of zero can be defined
- %- if the rank == 1, checks whether same directions
- boul = 1;
- if ~spm_sp('isinspp',sX,c), c = spm_sp('oPp:',sX,c); end;
- if rank(c) > 1 || any(any(c'*c < 0)), boul = 0; end;
- %=======================================================================
- function [idxFc2, idxFc1] = sf_in(Fc1, sX, Fc2)
- L2 = length(Fc2);
- L1 = length(Fc1);
- idxFc1 = []; idxFc2 = [];
- for j=1:L1
- %- project Fc1(j).c if not estimable
- if ~spm_sp('isinspp',sX,Fc1(j).c), %- warning ?
- c1 = spm_sp('oPp:',sX,Fc1(j).c);
- else
- c1 = Fc1(j).c;
- end
- sc1 = spm_sp('Set',c1);
- S = Fc1(j).STAT;
- boul = 0;
- for i =1:L2
- if Fc2(i).STAT == S
- %- the same statistics. else just go on to the next contrast
- boul = spm_sp('==',sc1,spm_sp('oPp',sX,Fc2(i).c));
- %- if they are the same space and T stat (same direction),
- %- then check wether they are in the same ORIENTATION
- %- works because size(X1o,2) == 1, else .* with (Fc1(j).c'*Fc2(i).c)
- if boul && S == 'T'
- atmp = sf_X1o(Fc1(j),sX);
- btmp = sf_X1o(Fc2(i),sX);
- boul = ~any(any( (atmp' * btmp) < 0 ));
- end
- %- note the indices
- if boul, idxFc1 = [idxFc1 j]; idxFc2 = [idxFc2 i]; end
- end
- end
- end %- for j=1:L1
- %=======================================================================
- function idx = sf_notunique(Fc, sX)
- %- works recursively ...
- %- and use the fact that [] + i == []
- %- quite long for large sets ...
- l = length(Fc);
- if l == 1, idx = [];
- else
- idx = [ (1+sf_in(Fc(1),sX,Fc(2:l))) (1+sf_notunique(Fc(2:l), sX))];
- end
|