diff --git a/@file_array/cat.m b/@file_array/cat.m index 7671e34..df738ef 100644 --- a/@file_array/cat.m +++ b/@file_array/cat.m @@ -5,7 +5,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: cat.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: cat.m 4136 2010-12-09 22:22:28Z guillaume $ if dr>32 || dr<0, error('Unknown command option.'); end; @@ -36,5 +36,5 @@ error('All matrices on a row in the bracketed expression must have the same number of rows.'); else o = vertcat(tmp{:}); - o = class(o,'file_array'); + o = file_array(o); end; diff --git a/@file_array/disp.m b/@file_array/disp.m index 49fc219..5a81693 100644 --- a/@file_array/disp.m +++ b/@file_array/disp.m @@ -4,7 +4,7 @@ function disp(obj) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: disp.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: disp.m 4136 2010-12-09 22:22:28Z guillaume $ if numel(struct(obj))>1, @@ -19,7 +19,7 @@ function disp(obj) fprintf('%d\n',sz(end)); end; else - display(mystruct(obj)) + disp(mystruct(obj)) end; return; %======================================================================= diff --git a/@file_array/file_array.m b/@file_array/file_array.m index 34c9e1c..59819a4 100644 --- a/@file_array/file_array.m +++ b/@file_array/file_array.m @@ -13,7 +13,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: file_array.m 1340 2008-04-09 17:11:23Z john $ +% $Id: file_array.m 4136 2010-12-09 22:22:28Z guillaume $ if nargin==1 @@ -38,5 +38,5 @@ if nargin>=7, a = permission(a,varargin{7}); end; a.pos = ones(size(a.dim)); -a = class(a,'file_array'); +a = file_array(a); diff --git a/@file_array/private/datatypes.m b/@file_array/private/datatypes.m index e3e8c45..0e2ea0b 100644 --- a/@file_array/private/datatypes.m +++ b/@file_array/private/datatypes.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: datatypes.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: datatypes.m 4136 2010-12-09 22:22:28Z guillaume $ persistent dtype @@ -24,10 +24,10 @@ 1280,'UINT64' ,'uint64' ,@uint64 ,1,8 ,t,t,f 16 ,'FLOAT32' ,'float32' ,@single ,1,4 ,f,f,t 64 ,'FLOAT64' ,'double' ,@double ,1,8 ,f,f,t - 1536,'FLOAT128' ,'float128',@crash ,1,16 ,f,f,f + 1536,'FLOAT128' ,'float128',@error ,1,16 ,f,f,f 32 ,'COMPLEX64' ,'float32' ,@single ,2,4 ,f,f,f 1792,'COMPLEX128','double' ,@double ,2,8 ,f,f,f - 2048,'COMPLEX256','float128',@crash ,2,16 ,f,f,f + 2048,'COMPLEX256','float128',@error ,2,16 ,f,f,f 128 ,'RGB24' ,'uint8' ,@uint8 ,3,1 ,t,t,f}; dtype = struct(... 'code' ,table(:,1),... diff --git a/@file_array/subsasgn.m b/@file_array/subsasgn.m index a47c540..6c2f7bc 100644 --- a/@file_array/subsasgn.m +++ b/@file_array/subsasgn.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: subsasgn.m 1355 2008-04-10 10:52:35Z vladimir $ +% $Id: subsasgn.m 4136 2010-12-09 22:22:28Z guillaume $ if isempty(subs) @@ -47,7 +47,7 @@ end; dm = [dm ones(1,16)]; -do = ones(1,16); +di = ones(1,16); args = {}; for i=1:length(subs.subs), if ischar(subs.subs{i}), @@ -56,7 +56,7 @@ else args{i} = int32(subs.subs{i}); end; - do(i) = length(args{i}); + di(i) = length(args{i}); end; for j=1:length(sobj), if strcmp(sobj(j).permission,'ro'), @@ -69,7 +69,7 @@ if numel(dat)~=1, subfun(sobj,double(dat),args{:}); else - dat1 = double(dat) + zeros(do); + dat1 = double(dat) + zeros(di); subfun(sobj,dat1,args{:}); end; else diff --git a/@file_array/subsref.m b/@file_array/subsref.m index e59bcdd..0f952ff 100644 --- a/@file_array/subsref.m +++ b/@file_array/subsref.m @@ -5,7 +5,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: subsref.m 3958 2010-06-30 16:24:46Z guillaume $ +% $Id: subsref.m 4136 2010-12-09 22:22:28Z guillaume $ if isempty(subs), return; end @@ -39,7 +39,7 @@ end end -do = ones(16,1); +di = ones(16,1); args = cell(1,length(subs.subs)); for i=1:length(subs.subs) if ischar(subs.subs{i}) @@ -58,7 +58,7 @@ else args{i} = subs.subs{i}; end - do(i) = length(args{i}); + di(i) = length(args{i}); end if length(sobj)==1 @@ -66,7 +66,7 @@ else dt = datatypes; dt = dt([dt.code]==sobj(1).dtype); % assuming identical datatypes - t = zeros(do',func2str(dt.conv)); + t = zeros(di',func2str(dt.conv)); for j=1:length(sobj) ps = [sobj(j).pos ones(1,length(args))]; dm = [sobj(j).dim ones(1,length(args))]; diff --git a/@gifti/display.m b/@gifti/display.m index 9f151fe..ce56cd0 100644 --- a/@gifti/display.m +++ b/@gifti/display.m @@ -6,7 +6,7 @@ function display(this) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: display.m 2076 2008-09-10 12:34:08Z guillaume $ +% $Id: display.m 4182 2011-02-01 12:29:09Z guillaume $ display_name = inputname(1); if isempty(display_name) @@ -17,6 +17,9 @@ function display(this) eval([display_name ' = struct(this);']); eval(['display(' display_name ');']); else + disp(' ') + disp([display_name ' =']); + disp(' '); eval([display_name ' = this;']); - eval(['builtin(''display'',' display_name ');']); + eval(['disp(' display_name ');']); end \ No newline at end of file diff --git a/@gifti/private/read_gifti_file.m b/@gifti/private/read_gifti_file.m index 74861b3..a5641fa 100644 --- a/@gifti/private/read_gifti_file.m +++ b/@gifti/private/read_gifti_file.m @@ -7,7 +7,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: read_gifti_file.m 3999 2010-07-19 10:54:18Z guillaume $ +% $Id: read_gifti_file.m 4013 2010-07-22 17:12:45Z guillaume $ % Import XML-based GIfTI file %-------------------------------------------------------------------------- @@ -23,7 +23,7 @@ error('[GIFTI] %s is not a GIFTI 1.0 file.', filename); end attr = cell2mat(attributes(t,'get',root(t))); -attr = cell2struct({attr.val},strrep({attr.key},':','_'),2); +attr = cell2struct({attr.val},strrep({attr.key},':','___'),2); if ~all(ismember({'Version','NumberOfDataArrays'},fieldnames(attr))) error('[GIFTI] Missing mandatory attributes for GIFTI root element.'); end diff --git a/@gifti/save.m b/@gifti/save.m index 4ecffb7..5694757 100644 --- a/@gifti/save.m +++ b/@gifti/save.m @@ -10,7 +10,7 @@ function save(this,filename,encoding) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: save.m 3999 2010-07-19 10:54:18Z guillaume $ +% $Id: save.m 4022 2010-07-28 12:50:20Z guillaume $ error(nargchk(1,3,nargin)); @@ -66,9 +66,9 @@ function save(this,filename,encoding) % Defaults for DataArray's attributes %-------------------------------------------------------------------------- [unused,unused,mach] = fopen(fid); -if ~isempty(strmatch('ieee-be',mach)) +if strncmp('ieee-be',mach,7) def.Endian = 'BigEndian'; -elseif ~isempty(strmatch('ieee-le',mach)) +elseif strncmp('ieee-le',mach,7) def.Endian = 'LittleEndian'; else error('[GIFTI] Unknown byte order "%s".',mach); diff --git a/@gifti/subsref.m b/@gifti/subsref.m index 7671693..19af133 100644 --- a/@gifti/subsref.m +++ b/@gifti/subsref.m @@ -4,13 +4,14 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: subsref.m 3999 2010-07-19 10:54:18Z guillaume $ +% $Id: subsref.m 4136 2010-12-09 22:22:28Z guillaume $ -if length(this) > 1 +if length(this) > 1 && ~strcmp(subs(1).type,'()') warning('Not implemented.'); for i=1:numel(this) varargout{i} = subsref(this(i),subs); end + return; end switch subs(1).type diff --git a/@meeg/badchannels.m b/@meeg/badchannels.m index f1b9388..ac9d713 100644 --- a/@meeg/badchannels.m +++ b/@meeg/badchannels.m @@ -5,18 +5,19 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: badchannels.m 3942 2010-06-21 14:03:28Z vladimir $ +% $Id: badchannels.m 4040 2010-08-20 23:25:46Z vladimir $ -if length(varargin) == 2 + +if length(varargin) == 2 && ~isempty(varargin{1}) % make sure that the two inputs for set are the same length if ~(length(varargin{2}) == 1 | (length(varargin{1}) == length(varargin{2}))) error('Use either same vector length or scalar for value'); end end -if numel(varargin) >= 1 - if ~(varargin{1} >= 1 & varargin{1} <= nchannels(this)) +if numel(varargin) >= 1 && ~isempty(varargin{1}) + if ~(all(varargin{1} >= 1) && all(varargin{1} <= nchannels(this))) error('Channel number of out range.'); end end diff --git a/@meeg/clone.m b/@meeg/clone.m index d138cbf..541aee2 100644 --- a/@meeg/clone.m +++ b/@meeg/clone.m @@ -11,7 +11,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel, Vladimir Litvak -% $Id: clone.m 3807 2010-04-06 19:29:08Z vladimir $ +% $Id: clone.m 4207 2011-02-22 10:48:36Z christophe $ if nargin < 4 reset = 0; @@ -32,11 +32,26 @@ if isempty(pth) pth = this.path; end -newFileName = [fullfile(pth,fname),ext]; +newFileName = [fullfile(pth,fname),'.dat']; % copy the file_array d = this.data.y; % d.fname = newFileName; -d.dim = dim; +dim_o = d.dim; + +% This takes care of an issue specific to data files with a scaling factor +% which are not officially supported in SPM8 (float without scaling). +% Also assuming scaling is the *same* for all channels... +if dim(1)>dim_o(1) && length(d.scl_slope)>1 + % adding channel to montage and scl_slope defined for old montage + % -> need to increase size of scl_slope + v_slope = mode(d.scl_slope); + if length(v_slope)>1 + warning(['Trying to guess the scaling factor for new channels.',... + ' This factor might be wrong now.']); + end + d.scl_slope = [d.scl_slope' ones(1,dim(1)-dim_o(1))*v_slope]'; +end +d.dim = dim; % physically initialise file if length(dim) == 3 diff --git a/@meeg/frequencies.m b/@meeg/frequencies.m index 2b95477..9fd8f01 100644 --- a/@meeg/frequencies.m +++ b/@meeg/frequencies.m @@ -5,7 +5,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: frequencies.m 3579 2009-11-18 16:21:55Z vladimir $ +% $Id: frequencies.m 4015 2010-07-23 16:35:03Z vladimir $ if nargin < 3 if strncmpi(transformtype(this), 'TF',2) @@ -34,7 +34,11 @@ error('Wrong frequency axis or indices'); end - this.transform.frequencies(ind) = f; + if length(ind) == size(this.data.y, 2) + this.transform.frequencies = f; + else + this.transform.frequencies(ind) = f; + end res = this; end diff --git a/@meeg/private/checkmeeg.m b/@meeg/private/checkmeeg.m index 46386d4..0ee19f9 100644 --- a/@meeg/private/checkmeeg.m +++ b/@meeg/private/checkmeeg.m @@ -9,7 +9,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: checkmeeg.m 3978 2010-07-08 14:26:39Z vladimir $ +% $Id: checkmeeg.m 4207 2011-02-22 10:48:36Z christophe $ if nargin==1 option = 'basic'; @@ -64,10 +64,24 @@ end for k = 1:Ntrials - if isnumeric(meegstruct.trials(k).label) - meegstruct.trials(k).label = num2str(meegstruct.trials(k).label); + + label = meegstruct.trials(k).label; + + if iscell(label) && numel(label) == 1 + label = label{1}; end + if isnumeric(label) + label = num2str(label); + end + + if isa(label, 'char') + meegstruct.trials(k).label = label; + else + meegstruct.trials(k).label = 'Unknown'; + disp('checkmeeg: some trial labels were not strings, changing back to ''Unknown'''); + end + if length(meegstruct.trials(k).bad)>1 || ~ismember(meegstruct.trials(k).bad, [0, 1]) disp(['checkmeeg: illegal value for bad flag in trial ' num2str(k) ', setting to zero.']); meegstruct.trials(k).bad = 0; @@ -135,6 +149,11 @@ else [meegstruct.channels(find(cellfun('isempty', {meegstruct.channels.bad}))).bad] = deal(0); end + + for i = 1:Nchannels + meegstruct.channels(i).bad = double(~~meegstruct.channels(i).bad); + end + if ~isfield(meegstruct.channels, 'type') disp('checkmeeg: no channel type, assigning default'); [meegstruct.channels.type] = deal('Other'); @@ -199,12 +218,20 @@ end if isa(meegstruct.data.y, 'file_array') + % catching up (unlikely case) where filearray.fname is + % different from data.fnamedat -> set data.fnamedat + [junk, yfname, yext] = fileparts(meegstruct.data.y.fname); + [junk, dfname, dext] = fileparts(meegstruct.data.fnamedat); + if ~strcmp([yfname yext],[dfname dext]) + meegstruct.data.fnamedat = [yfname yext]; + end + % save original file_array scale & offset, just in case + sav_sc = meegstruct.data.y.scl_slope; + sav_os = meegstruct.data.y.offset; try % Try reading data, i.e. check if it's a "good" filearray meegstruct.data.y(1, 1, 1); catch - % save original file_array scale, just in case - sav_sc = meegstruct.data.y.scl_slope; meegstruct.data.y = []; end end @@ -235,9 +262,14 @@ error('Unknown transform type'); end % and restore original file_array scale, if available (exist) & useful (~=[]) - if exist('sav_sc','var') && ~isempty(sav_sc) + if exist('sav_sc','var') && ~isempty(sav_sc) && ... + size(meegstruct.data.y, 1) == length(sav_sc) meegstruct.data.y.scl_slope = sav_sc; end + % and restore original file_array offset, if available (exist) & useful (~=0) + if exist('sav_os','var') && sav_os + meegstruct.data.y.offset = sav_os; + end end diff --git a/@nifti/disp.m b/@nifti/disp.m index 3f2dea3..68e0efb 100644 --- a/@nifti/disp.m +++ b/@nifti/disp.m @@ -4,7 +4,7 @@ function disp(obj) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: disp.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: disp.m 4136 2010-12-09 22:22:28Z guillaume $ sz = size(obj); @@ -18,6 +18,6 @@ function disp(obj) fprintf('%d\n',sz(end)); end; if prod(sz)==1, - display(structn(obj)) + disp(structn(obj)) end; return; diff --git a/@nifti/nifti.m b/@nifti/nifti.m index dbc0987..76c3e63 100644 --- a/@nifti/nifti.m +++ b/@nifti/nifti.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: nifti.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: nifti.m 4270 2011-03-29 16:26:26Z john $ switch nargin @@ -59,7 +59,7 @@ dim = double(vol.hdr.dim); dim = dim(2:(dim(1)+1)); dt = double(vol.hdr.datatype); - offs = double(vol.hdr.vox_offset); + offs = max(double(vol.hdr.vox_offset),0); if ~vol.hdr.scl_slope && ~vol.hdr.scl_inter, vol.hdr.scl_slope = 1; diff --git a/@nifti/subsasgn.m b/@nifti/subsasgn.m index 5d92060..440202d 100644 --- a/@nifti/subsasgn.m +++ b/@nifti/subsasgn.m @@ -5,7 +5,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: subsasgn.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: subsasgn.m 4136 2010-12-09 22:22:28Z guillaume $ switch subs(1).type, @@ -16,11 +16,11 @@ objs = struct(obj); for i=1:length(varargin), val = varargin{i}; - obji = class(objs(i),'nifti'); + obji = nifti(objs(i)); obji = fun(obji,subs,val); objs(i) = struct(obji); end; - obj = class(objs,'nifti'); + obj = nifti(objs); case {'()'}, objs = struct(obj); @@ -33,7 +33,7 @@ %end; for i=1:numel(t), val = varargin{1}; - obji = class(t(i),'nifti'); + obji = nifti(t(i)); obji = subsasgn(obji,subs(2:end),val); t(i) = struct(obji); end; @@ -51,7 +51,7 @@ error('Assignment between unlike types is not allowed.'); end; end; - obj = class(objs,'nifti'); + obj = nifti(objs); otherwise error('Cell contents reference from a non-cell array object.'); @@ -82,7 +82,7 @@ if ~isfield(obj.hdr,'magic'), error('Not a NIFTI-1 header'); end; if length(subs)>1, % && ~strcmpi(subs(1).subs,{'raw','dat'}), - val0 = subsref(class(obj,'nifti'),subs(1)); + val0 = subsref(nifti(obj),subs(1)); val1 = subsasgn(val0,subs(2:end),val); else val1 = val; @@ -333,7 +333,7 @@ objs(ii) = obj; end - obj = class(objs,'nifti'); + obj = nifti(objs); otherwise error('This should not happen.'); @@ -345,11 +345,11 @@ function obj = assigndat(obj,val) if isa(val,'file_array'), sz = size(val); - if numel(sz)>8, + if numel(sz)>7, error('Too many dimensions in data.'); end; - sz = [sz 1 1 1 1 1 1 1 1]; - sz = sz(1:8); + sz = [sz 1 1 1 1 1 1 1]; + sz = sz(1:7); sval = struct(val); d = findindict(sval.dtype,'dtype'); if isempty(d) @@ -359,10 +359,10 @@ [pth,nam,suf] = fileparts(sval.fname); if any(strcmp(suf,{'.img','.IMG'})) val.offset = max(sval.offset,0); - obj.hdr.magic = 'ni1'; + obj.hdr.magic = ['ni1' char(0)]; elseif any(strcmp(suf,{'.nii','.NII'})) val.offset = max(sval.offset,352); - obj.hdr.magic = 'n+1'; + obj.hdr.magic = ['n+1' char(0)]; else error(['Unknown filename extension (' suf ').']); end; diff --git a/@nifti/subsref.m b/@nifti/subsref.m index 62878d8..b55620c 100644 --- a/@nifti/subsref.m +++ b/@nifti/subsref.m @@ -39,7 +39,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: subsref.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: subsref.m 4136 2010-12-09 22:22:28Z guillaume $ varargout = rec(opt,subs); @@ -51,7 +51,7 @@ c = {}; opts = struct(opt); for ii=1:numel(opts) - opt = class(opts(ii),'nifti'); + opt = nifti(opts(ii)); %if ~isstruct(opt) % error('Attempt to reference field of non-structure array.'); %end; @@ -228,12 +228,12 @@ if length(subs)>1 c = {}; for i=1:numel(t), - ti = class(t(i),'nifti'); + ti = nifti(t(i)); ti = rec(ti,subs(2:end)); c = {c{:}, ti{:}}; end; else - c = {class(t,'nifti')}; + c = {nifti(t)}; end; otherwise diff --git a/@xmltree/private/xml_findstr.c b/@xmltree/private/xml_findstr.c index 6c3c978..7a19e57 100644 --- a/@xmltree/private/xml_findstr.c +++ b/@xmltree/private/xml_findstr.c @@ -1,7 +1,7 @@ #include "mex.h" /* - * $Id: xml_findstr.c 1460 2008-04-21 17:43:18Z guillaume $ + * $Id: xml_findstr.c 4151 2011-01-07 18:09:25Z guillaume $ * Guillaume Flandin */ @@ -10,16 +10,18 @@ - allows to search only the n first occurences of a pattern - allows to search only in a substring (given an index of the beginning) - Matlab hack: + MATLAB hack: - doesn't use mxGetString to prevent a copy of the string. - - assumes Matlab stores strings as unsigned short (Unicode 16 bits) + - assumes MATLAB stores strings as unsigned short (Unicode 16 bits) matrix.h: typedef uint16_T mxChar; - (that's the case for Matlab 5.* and 6.* but Matlab 4.* stores strings - as double) + (that's the case for MATLAB 5.*, 6.* and 7.* but MATLAB 4.* stores strings + as double and Octave as char, see src/mxarray.h) */ /* Comment the following line to use standard mxGetString (slower) */ +#if !defined (HAVE_OCTAVE) #define __HACK_MXCHAR__ +#endif void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { diff --git a/@xmltree/private/xml_parser.m b/@xmltree/private/xml_parser.m index f05f9ca..0ec5da3 100644 --- a/@xmltree/private/xml_parser.m +++ b/@xmltree/private/xml_parser.m @@ -16,7 +16,7 @@ % Copyright (C) 2002-2008 http://www.artefact.tk/ % Guillaume Flandin -% $Id: xml_parser.m 1460 2008-04-21 17:43:18Z guillaume $ +% $Id: xml_parser.m 4013 2010-07-22 17:12:45Z guillaume $ % XML Processor for MATLAB (The Mathworks, Inc.). % Copyright (C) 2002-2008 Guillaume Flandin @@ -308,8 +308,8 @@ while 1, eq = xml_findstr(str,'=',1,1); if isempty(str) || isempty(eq), return; end - id = xml_findstr(str,'"',1,1); % should also look for '''' - nextid = xml_findstr(str,'"',id+1,1);% rather than only '"' + id = sort([xml_findstr(str,'"',1,1),xml_findstr(str,'''',1,1)]); id=id(1); + nextid = sort([xml_findstr(str,'"',id+1,1),xml_findstr(str,'''',id+1,1)]);nextid=nextid(1); nbattr = nbattr + 1; all{nbattr}.key = strip(str(1:(eq-1))); all{nbattr}.val = entity(str((id+1):(nextid-1))); diff --git a/Contents.m b/Contents.m index dde85d3..5e9e743 100644 --- a/Contents.m +++ b/Contents.m @@ -1,5 +1,5 @@ % Statistical Parametric Mapping -% Version 4010 (SPM8) 21-Jul-10 +% Version 4290 (SPM8) 04-Apr-11 %__________________________________________________________________________ % ___ ____ __ __ % / __)( _ \( \/ ) @@ -40,9 +40,9 @@ % You should have received a copy of the GNU General Public License along % with SPM, in spm_LICENCE.man. If not, see . %__________________________________________________________________________ -% Copyright (C) 1991,1994-2003,2005-2010 Wellcome Trust Centre for Neuroimaging +% Copyright (C) 1991,1994-2011 Wellcome Trust Centre for Neuroimaging -% $Id: Contents.m 4008 2010-07-21 12:57:02Z guillaume $ +% $Id: Contents.m 4289 2011-04-04 14:47:35Z guillaume $ %========================================================================== % PROGRAMMERS NOTE: diff --git a/config/spm_cfg.m b/config/spm_cfg.m index 8142f93..09bbf11 100644 --- a/config/spm_cfg.m +++ b/config/spm_cfg.m @@ -3,7 +3,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg.m 3881 2010-05-07 21:02:57Z vladimir $ +% $Id: spm_cfg.m 4257 2011-03-18 15:28:29Z vladimir $ %_______________________________________________________________________ % temporal Temporal @@ -52,7 +52,7 @@ source.tag = 'source'; source.name = 'M/EEG Source reconstruction'; source.help = {'M/EEG source reconstruction.'}; -source.values = {spm_cfg_eeg_inv_headmodel, spm_cfg_eeg_inv_invert, spm_cfg_eeg_inv_results}; +source.values = {spm_cfg_eeg_inv_headmodel, spm_cfg_eeg_inv_invert, spm_cfg_eeg_inv_results, spm_cfg_eeg_inv_extract}; % --------------------------------------------------------------------- % meeg Meeg % --------------------------------------------------------------------- diff --git a/config/spm_cfg_checkreg.m b/config/spm_cfg_checkreg.m index 1fb473b..37cf0e6 100644 --- a/config/spm_cfg_checkreg.m +++ b/config/spm_cfg_checkreg.m @@ -1,35 +1,38 @@ function checkreg = spm_cfg_checkreg -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE -%_______________________________________________________________________ +% SPM Configuration file for Check Reg +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_checkreg.m 1295 2008-04-02 14:31:24Z volkmar $ +% $Id: spm_cfg_checkreg.m 4205 2011-02-21 15:39:08Z guillaume $ -rev = '$Rev: 1295 $'; -% --------------------------------------------------------------------- +%-------------------------------------------------------------------------- % data Images to Display -% --------------------------------------------------------------------- +%-------------------------------------------------------------------------- data = cfg_files; data.tag = 'data'; data.name = 'Images to Display'; data.help = {'Images to display.'}; -data.filter = 'image'; +data.filter = 'image'; data.ufilter = '.*'; data.num = [1 15]; -% --------------------------------------------------------------------- + +%-------------------------------------------------------------------------- % checkreg Check Registration -% --------------------------------------------------------------------- -checkreg = cfg_exbranch; -checkreg.tag = 'checkreg'; -checkreg.name = 'Check Registration'; -checkreg.val = {data }; -checkreg.help = { - 'Orthogonal views of one or more images are displayed. Clicking in any image moves the centre of the orthogonal views. Images are shown in orientations relative to that of the first selected image. The first specified image is shown at the top-left, and the last at the bottom right. The fastest increment is in the left-to-right direction (the same as you are reading this).' - '' - 'If you have put your images in the correct file format, then (possibly after specifying some rigid-body rotations):' - ' The top-left image is coronal with the top (superior) of the head displayed at the top and the left shown on the left. This is as if the subject is viewed from behind.' - ' The bottom-left image is axial with the front (anterior) of the head at the top and the left shown on the left. This is as if the subject is viewed from above.' - ' The top-right image is sagittal with the front (anterior) of the head at the left and the top of the head shown at the top. This is as if the subject is viewed from the left.' +%-------------------------------------------------------------------------- +checkreg = cfg_exbranch; +checkreg.tag = 'checkreg'; +checkreg.name = 'Check Registration'; +checkreg.val = {data }; +checkreg.help = { + 'Orthogonal views of one or more images are displayed. Clicking in any image moves the centre of the orthogonal views. Images are shown in orientations relative to that of the first selected image. The first specified image is shown at the top-left, and the last at the bottom right. The fastest increment is in the left-to-right direction (the same as you are reading this).' + '' + 'If you have put your images in the correct file format, then (possibly after specifying some rigid-body rotations):' + ' The top-left image is coronal with the top (superior) of the head displayed at the top and the left shown on the left. This is as if the subject is viewed from behind.' + ' The bottom-left image is axial with the front (anterior) of the head at the top and the left shown on the left. This is as if the subject is viewed from above.' + ' The top-right image is sagittal with the front (anterior) of the head at the left and the top of the head shown at the top. This is as if the subject is viewed from the left.' }'; -checkreg.prog = @spm_check_registration; +checkreg.prog = @check_reg; + +%========================================================================== +function check_reg(job) +spm_check_registration(char(job.data)); \ No newline at end of file diff --git a/config/spm_cfg_coreg.m b/config/spm_cfg_coreg.m index 892bc2e..792068b 100644 --- a/config/spm_cfg_coreg.m +++ b/config/spm_cfg_coreg.m @@ -3,7 +3,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_coreg.m 3596 2009-11-25 19:17:07Z guillaume $ +% $Id: spm_cfg_coreg.m 4269 2011-03-29 16:03:43Z guillaume $ % --------------------------------------------------------------------- % ref Reference Image @@ -99,7 +99,7 @@ % --------------------------------------------------------------------- estimate = cfg_exbranch; estimate.tag = 'estimate'; -estimate.name = 'Coreg: Estimate'; +estimate.name = 'Coregister: Estimate'; estimate.val = {ref source other eoptions }; estimate.help = { 'The registration method used here is based on work by Collignon et al/* \cite{collignon95}*/. The original interpolation method described in this paper has been changed in order to give a smoother cost function. The images are also smoothed slightly, as is the histogram. This is all in order to make the cost function as smooth as possible, to give faster convergence and less chance of local minima.' @@ -209,7 +209,7 @@ % --------------------------------------------------------------------- write = cfg_exbranch; write.tag = 'write'; -write.name = 'Coreg: Reslice'; +write.name = 'Coregister: Reslice'; write.val = {refwrite source roptions }; write.help = {'Reslice images to match voxel-for-voxel with an image defining some space. The resliced images are named the same as the originals except that they are prefixed by ''r''.'}; write.prog = @spm_run_coreg_reslice; @@ -229,7 +229,7 @@ % --------------------------------------------------------------------- estwrite = cfg_exbranch; estwrite.tag = 'estwrite'; -estwrite.name = 'Coreg: Estimate & Reslice'; +estwrite.name = 'Coregister: Estimate & Reslice'; estwrite.val = {ref source other eoptions roptions }; estwrite.help = { 'The registration method used here is based on work by Collignon et al/* \cite{collignon95}*/. The original interpolation method described in this paper has been changed in order to give a smoother cost function. The images are also smoothed slightly, as is the histogram. This is all in order to make the cost function as smooth as possible, to give faster convergence and less chance of local minima.' @@ -245,7 +245,7 @@ % --------------------------------------------------------------------- coreg = cfg_choice; coreg.tag = 'coreg'; -coreg.name = 'Coreg'; +coreg.name = 'Coregister'; coreg.help = { 'Within-subject registration using a rigid-body model. A rigid-body transformation (in 3D) can be parameterised by three translations and three rotations about the different axes.' '' diff --git a/config/spm_cfg_defs.m b/config/spm_cfg_defs.m index a360b5a..de8db61 100644 --- a/config/spm_cfg_defs.m +++ b/config/spm_cfg_defs.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_cfg_defs.m 3804 2010-03-31 16:16:21Z ged $ +% $Id: spm_cfg_defs.m 4136 2010-12-09 22:22:28Z guillaume $ hsummary = {[... 'This is a utility for working with deformation fields. ',... @@ -81,9 +81,9 @@ 'Specify the image file on which to base the dimensions, orientation etc.'}; hid = {[... -'This option generates an identity transform, but this can be useful for '... -'changing the dimensions of the resulting deformation (and any images that '... -'are generated from it). Dimensions, orientation etc are derived from '... +'This option generates an identity transform, but this can be useful for ',... +'changing the dimensions of the resulting deformation (and any images that ',... +'are generated from it). Dimensions, orientation etc are derived from ',... 'an image.']}; def = files('Deformation Field','def','.*y_.*\.nii$',[1 1]); diff --git a/config/spm_cfg_dicom.m b/config/spm_cfg_dicom.m index 6c6f876..5eebbbc 100644 --- a/config/spm_cfg_dicom.m +++ b/config/spm_cfg_dicom.m @@ -3,7 +3,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_dicom.m 3697 2010-01-22 17:07:18Z guillaume $ +% $Id: spm_cfg_dicom.m 4012 2010-07-22 12:45:53Z volkmar $ % --------------------------------------------------------------------- % data DICOM files @@ -29,15 +29,17 @@ '' '* Output directory: ./: Convert into the output directory, starting with a PatientName subdirectory.' '* No directory hierarchy: Convert all files into the output directory, without sequence/series subdirectories'}'; -root.labels = {'Output directory: ./' - 'Output directory: ./' - 'Output directory: .//' - 'Output directory: ./' +root.labels = {'Output directory: .//' + 'Output directory: .//' + 'Output directory: .///' + 'Output directory: .//' + 'Output directory: ./' 'No directory hierarchy'}'; root.values = {'date_time' 'patid' 'patid_date' 'patname' + 'series' 'flat'}'; root.def = @(val)spm_get_defaults('dicom.root', val{:}); % --------------------------------------------------------------------- diff --git a/config/spm_cfg_disp.m b/config/spm_cfg_disp.m index 06d9cd9..fc709dc 100644 --- a/config/spm_cfg_disp.m +++ b/config/spm_cfg_disp.m @@ -1,29 +1,28 @@ function disp = spm_cfg_disp -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE -%_______________________________________________________________________ +% SPM Configuration file for Image Display +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_disp.m 1295 2008-04-02 14:31:24Z volkmar $ +% $Id: spm_cfg_disp.m 4205 2011-02-21 15:39:08Z guillaume $ -rev = '$Rev: 1295 $'; -% --------------------------------------------------------------------- +%------------------------------------------------------------------------- % data Image to Display -% --------------------------------------------------------------------- +%------------------------------------------------------------------------- data = cfg_files; data.tag = 'data'; data.name = 'Image to Display'; data.help = {'Image to display.'}; -data.filter = 'image'; +data.filter = 'image'; data.ufilter = '.*'; data.num = [1 1]; -% --------------------------------------------------------------------- + +%-------------------------------------------------------------------------- % disp Display Image -% --------------------------------------------------------------------- +%-------------------------------------------------------------------------- disp = cfg_exbranch; disp.tag = 'disp'; disp.name = 'Display Image'; -disp.val = {data }; +disp.val = {data}; disp.help = { 'This is an interactive facility that allows orthogonal sections from an image volume to be displayed. Clicking the cursor on either of the three images moves the point around which the orthogonal sections are viewed. The co-ordinates of the cursor are shown both in voxel co-ordinates and millimetres within some fixed framework. The intensity at that point in the image (sampled using the current interpolation scheme) is also given. The position of the cross-hairs can also be moved by specifying the co-ordinates in millimetres to which they should be moved. Clicking on the horizontal bar above these boxes will move the cursor back to the origin (analogous to setting the cross-hair position (in mm) to [0 0 0]).' '' @@ -36,9 +35,9 @@ ' Datatype - the computer representation of each voxel.' ' Intensity - scale-factors and possibly a DC offset.' ' Miscellaneous other information about the image.' - ' Vox size - the distance (in mm) between the centres of neighbouring voxels.' + ' Vox size - the distance (in mm) between the centres of neighbouring voxels.' ' Origin - the voxel at the origin of the co-ordinate system' - ' DIr Cos - Direction cosines. This is a widely used representation of the orientation of an image.' + ' DIr Cos - Direction cosines. This is a widely used representation of the orientation of an image.' '' 'There are also a few options for different resampling modes, zooms etc. You can also flip between voxel space (as would be displayed by Analyze) or world space (the orientation that SPM considers the image to be in). If you are re-orienting the images, make sure that world space is specified. Blobs (from activation studies) can be superimposed on the images and the intensity windowing can also be changed.' '' @@ -49,4 +48,8 @@ ' The top-right image is sagittal with the front (anterior) of the head at the left and the top of the head shown at the top. This is as if the subject is viewed from the left.' '/*\begin{figure} \begin{center} \includegraphics[width=150mm]{images/disp1} \end{center} \caption{The Display routine. \label{disp1}}\end{figure} */' }'; -disp.prog = @spm_image; +disp.prog = @disp_image; + +%========================================================================== +function disp_image(job) +spm_image('Init', job.data{1}); diff --git a/config/spm_cfg_eeg_filter.m b/config/spm_cfg_eeg_filter.m index 1069a64..e32a309 100644 --- a/config/spm_cfg_eeg_filter.m +++ b/config/spm_cfg_eeg_filter.m @@ -4,9 +4,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_filter.m 3881 2010-05-07 21:02:57Z vladimir $ +% $Id: spm_cfg_eeg_filter.m 4212 2011-02-23 17:50:55Z vladimir $ -rev = '$Rev: 3881 $'; +rev = '$Rev: 4212 $'; D = cfg_files; D.tag = 'D'; D.name = 'File Name'; @@ -48,10 +48,10 @@ order = cfg_entry; order.tag = 'order'; order.name = 'Filter order'; -order.val = {[]}; +order.val = {5}; order.strtype = 'n'; -order.num = [0 1]; -order.help = {'Enter the filter order (leave empty for default)'}; +order.num = [1 1]; +order.help = {'Enter the filter order'}; flt = cfg_branch; flt.tag = 'filter'; diff --git a/config/spm_cfg_eeg_inv_extract.m b/config/spm_cfg_eeg_inv_extract.m new file mode 100644 index 0000000..cd95298 --- /dev/null +++ b/config/spm_cfg_eeg_inv_extract.m @@ -0,0 +1,121 @@ +function extract = spm_cfg_eeg_inv_extract +% configuration file for extracting source data from imaging source +% reconstruction +%_______________________________________________________________________ +% Copyright (C) 2011 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_cfg_eeg_inv_extract.m 4257 2011-03-18 15:28:29Z vladimir $ + +D = cfg_files; +D.tag = 'D'; +D.name = 'M/EEG datasets'; +D.filter = 'mat'; +D.num = [1 Inf]; +D.help = {'Select the M/EEG mat files.'}; + +val = cfg_entry; +val.tag = 'val'; +val.name = 'Inversion index'; +val.strtype = 'n'; +val.help = {'Index of the cell in D.inv where the inversion results are be stored.'}; +val.val = {1}; + +xyz = cfg_entry; +xyz.tag = 'xyz'; +xyz.name = 'Source location'; +xyz.strtype = 'r'; +xyz.num = [1 3]; +xyz.help = {'Source location (in MNI coordinates)'}; + +label = cfg_entry; +label.tag = 'label'; +label.name = 'Source label'; +label.strtype = 's'; +label.num = [1 Inf]; +label.help = {'Label for the source channel in the output file'}; + +source = cfg_branch; +source.tag = 'source'; +source.name = 'Source'; +source.val = {label, xyz}; + +sources = cfg_repeat; +sources.tag = 'sources'; +sources.name = 'Sources to extract'; +sources.values = {source}; +sources.num = [1 Inf]; +sources.help = {'Specify sources to extract data from'}; + +rad = cfg_entry; +rad.tag = 'rad'; +rad.name = 'VOI radius'; +rad.strtype = 'r'; +rad.num = [1 1]; +rad.val = {5}; +woi.help = {'Radius around each location to extract an eigenvariate from (mm).'}; + +type = cfg_menu; +type.tag = 'type'; +type.name = 'What to extract'; +type.help = {'What to extract: evoked activity or single trials.'}; +type.labels = {'Evoked', 'Single trials'}; +type.values = {'evoked', 'trials'}; +type.val = {'trials'}; + +fname = cfg_entry; +fname.tag = 'fname'; +fname.name = 'Output dataset name'; +fname.strtype = 's'; +fname.num = [0 Inf]; +fname.val = {''}; +fname.help = {'Output file name (empty for default)'}; + +extract = cfg_exbranch; +extract.tag = 'extract'; +extract.name = 'M/EEG source extraction'; +extract.val = {D, val, sources, rad, type, fname}; +extract.help = {'Extract source data from the results of inverse source reconstruction'}; +extract.prog = @run_extract; +extract.vout = @vout_extract; +extract.modality = {'EEG'}; + +function out = run_extract(job) + +source = []; +source.XYZ = cat(1, job.source.xyz); +source.label = {job.source.label}; +source.rad = job.rad; +source.type = job.type; + +if ~isempty(job.fname) + source.fname = job.fname; +end + +out.D = {}; + +for i = 1:numel(job.D) + D = spm_eeg_load(job.D{i}); + + D.val = job.val; + + if ~isfield(D.inv{D.val}, 'inverse') || ~isfield(D.inv{D.val}.inverse, 'J') + error(sprintf('Imaging source reconstruction is missing for subject %d', i)); + end + + D.inv{D.val}.source = source; + + Ds = spm_eeg_inv_extract(D); + + out.D{i, 1} = fullfile(Ds.path, Ds.fname); +end + +function dep = vout_extract(job) +% Output is always in field "D", no matter how job is structured +% Output is always in field "D", no matter how job is structured +dep = cfg_dep; +dep.sname = 'M/EEG dataset(s) extracted source data'; +% reference field "D" from output +dep.src_output = substruct('.','D'); +% this can be entered into any evaluated input +dep.tgt_spec = cfg_findspec({{'filter','mat'}}); diff --git a/config/spm_cfg_eeg_inv_headmodel.m b/config/spm_cfg_eeg_inv_headmodel.m index fb6b2ac..217e3df 100644 --- a/config/spm_cfg_eeg_inv_headmodel.m +++ b/config/spm_cfg_eeg_inv_headmodel.m @@ -5,7 +5,7 @@ % Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_cfg_eeg_inv_headmodel.m 3760 2010-03-08 17:00:30Z vladimir $ +% $Id: spm_cfg_eeg_inv_headmodel.m 4118 2010-11-10 14:48:16Z vladimir $ D = cfg_files; D.tag = 'D'; @@ -211,7 +211,7 @@ meegfid.fid.label = meegfid.fid.label(selection); mrifid = []; - mrifid.pnt = []; + mrifid.pnt = D.inv{val}.mesh.fid.pnt; mrifid.fid.pnt = []; mrifid.fid.label = {job.coregistration.coregspecify.fiducial.fidname}'; diff --git a/config/spm_cfg_eeg_montage.m b/config/spm_cfg_eeg_montage.m index 94af3c3..9c56d9c 100644 --- a/config/spm_cfg_eeg_montage.m +++ b/config/spm_cfg_eeg_montage.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_montage.m 3881 2010-05-07 21:02:57Z vladimir $ +% $Id: spm_cfg_eeg_montage.m 4212 2011-02-23 17:50:55Z vladimir $ D = cfg_files; D.tag = 'D'; @@ -20,21 +20,12 @@ montage.num = [1 1]; montage.help = {'Select a montage file.'}; -yes = cfg_const; -yes.tag = 'yes'; -yes.name = 'Keep the other channels'; -yes.val = {1}; - -no = cfg_const; -no.tag = 'no'; -no.name = 'Remove the other channels'; -no.val = {1}; - -keepothers = cfg_choice; +keepothers = cfg_menu; keepothers.tag = 'keepothers'; keepothers.name = 'Keep other channels'; -keepothers.values = {yes,no}; -keepothers.val = {yes}; +keepothers.labels = {'Yes', 'No'}; +keepothers.values = {'yes', 'no'}; +keepothers.val = {'no'}; keepothers.help = {'Specify whether you want to keep channels that are not contributing to the new channels'}; S = cfg_exbranch; @@ -50,12 +41,7 @@ % construct the S struct S.D = job.D{1}; S.montage = job.montage{1}; -if isfield(job.keepothers, 'yes') - S.keepothers = 'yes'; -else - S.keepothers = 'no'; -end - +S.keepothers = job.keepothers; out.D = spm_eeg_montage(S); out.Dfname = {fullfile(out.D.path, out.D.fname)}; diff --git a/config/spm_cfg_eeg_tf.m b/config/spm_cfg_eeg_tf.m index e12f75d..8d8a7f6 100644 --- a/config/spm_cfg_eeg_tf.m +++ b/config/spm_cfg_eeg_tf.m @@ -4,9 +4,9 @@ % Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_cfg_eeg_tf.m 3818 2010-04-13 14:36:31Z vladimir $ +% $Id: spm_cfg_eeg_tf.m 4257 2011-03-18 15:28:29Z vladimir $ -rev = '$Rev: 3818 $'; +rev = '$Rev: 4257 $'; D = cfg_files; D.tag = 'D'; @@ -29,7 +29,7 @@ frequencies.strtype = 'r'; frequencies.num = [0 Inf]; frequencies.val = {[]}; -frequencies.help = {'Frequencies of interest (as a vector), if empty 0-48 with optimal frequency bins ~1 Hz or above resolution'}; +frequencies.help = {'Frequencies of interest (as a vector), if empty 1-48 with optimal frequency bins ~1 Hz or above resolution'}; specest_funs = dir(fullfile(spm('dir'), 'spm_eeg_specest_*.m')); specest_funs = {specest_funs(:).name}; diff --git a/config/spm_cfg_eeg_tf_rescale.m b/config/spm_cfg_eeg_tf_rescale.m index a494105..647dfc6 100644 --- a/config/spm_cfg_eeg_tf_rescale.m +++ b/config/spm_cfg_eeg_tf_rescale.m @@ -4,7 +4,7 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_cfg_eeg_tf_rescale.m 3931 2010-06-16 15:28:54Z vladimir $ +% $Id: spm_cfg_eeg_tf_rescale.m 4287 2011-04-04 13:55:54Z vladimir $ %-------------------------------------------------------------------------- % D @@ -73,6 +73,15 @@ method_rel.val = {baseline}; method_rel.help = {'Relative.'}; +%-------------------------------------------------------------------------- +% method_zscore +%-------------------------------------------------------------------------- +method_zscore = cfg_branch; +method_zscore.tag = 'Zscore'; +method_zscore.name = 'Zscore'; +method_zscore.val = {baseline}; +method_zscore.help = {'Z score'}; + %-------------------------------------------------------------------------- % method_log %-------------------------------------------------------------------------- @@ -99,7 +108,7 @@ method.name = 'Rescale method'; method.val = {method_logr}; method.help = {'Select the rescale method.'}; -method.values = {method_logr method_diff method_rel method_log method_sqrt}; +method.values = {method_logr method_diff method_rel method_zscore method_log method_sqrt}; %-------------------------------------------------------------------------- % S @@ -126,7 +135,7 @@ S.tf.method = fieldnames(job.method); S.tf.method = S.tf.method{1}; switch lower(S.tf.method) - case {'logr','diff', 'rel'} + case {'logr','diff', 'rel', 'zscore'} S.tf.Sbaseline = 1e-3*job.method.(S.tf.method).baseline.Sbaseline; if ~(isempty(job.method.(S.tf.method).baseline.Db) || isequal(job.method.(S.tf.method).baseline.Db, {''})) S.tf.Db = job.method.(S.tf.method).baseline.Db{1}; diff --git a/config/spm_cfg_mfx.m b/config/spm_cfg_mfx.m new file mode 100644 index 0000000..f727bc6 --- /dev/null +++ b/config/spm_cfg_mfx.m @@ -0,0 +1,176 @@ +function mfx = spm_cfg_mfx +% SPM Configuration file for MFX +%______________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Guillaume Flandin +% $Id: spm_cfg_mfx.m 4023 2010-07-28 18:41:36Z guillaume $ + +% --------------------------------------------------------------------- +% dir Directory +% --------------------------------------------------------------------- +dir = cfg_files; +dir.tag = 'dir'; +dir.name = 'Directory'; +dir.help = {'Select a directory where the SPM.mat file containing the specified design matrix will be written.'}; +dir.filter = 'dir'; +dir.ufilter = '.*'; +dir.num = [1 1]; + +% --------------------------------------------------------------------- +% spmmat Select SPM.mat +% --------------------------------------------------------------------- +spmmat = cfg_files; +spmmat.tag = 'spmmat'; +spmmat.name = 'Select SPM.mat files'; +spmmat.help = {... + 'Select the SPM.mat files that contains first-level designs.' + 'They must have the same number of parameters for each session.' + ['These are assumed to represent session-specific realisations of ' ... + '2nd-level effects.']}; +spmmat.filter = 'mat'; +spmmat.ufilter = '^SPM\.mat$'; +spmmat.num = [1 Inf]; + +% --------------------------------------------------------------------- +% ffx Create first-level design +% --------------------------------------------------------------------- +ffx = cfg_exbranch; +ffx.tag = 'ffx'; +ffx.name = 'Create repeated-measure design'; +ffx.val = {dir spmmat}; +ffx.help = {'Create repeated-measure multi-session first-level design'}; +ffx.prog = @spm_local_ffx; +ffx.vout = @vout_ffx; + +% --------------------------------------------------------------------- +% spmmat Select SPM.mat +% --------------------------------------------------------------------- +spmmat = cfg_files; +spmmat.tag = 'spmmat'; +spmmat.name = 'Select SPM.mat'; +spmmat.help = {... + 'Design and estimation structure after a 1st-level analysis'}; +spmmat.filter = 'mat'; +spmmat.ufilter = '^SPM\.mat$'; +spmmat.num = [1 1]; + +% --------------------------------------------------------------------- +% spec MFX Specification +% --------------------------------------------------------------------- +spec = cfg_exbranch; +spec.tag = 'spec'; +spec.name = 'MFX Specification'; +spec.val = {spmmat}; +spec.help = {'MFX Specification'}; +spec.prog = @spm_local_mfx; +spec.vout = @vout_mfx; + +% --------------------------------------------------------------------- +% mfx Mixed-effects (MFX) analysis +% --------------------------------------------------------------------- +mfx = cfg_choice; +mfx.tag = 'mfx'; +mfx.name = 'Mixed-effects (MFX) analysis'; +mfx.help = {'Mixed-effects (MFX) analysis'}; +mfx.values = {ffx spec}; + +% ===================================================================== +function out = spm_local_ffx(job) +spmmat = job.spmmat; +SPMS = cell(size(spmmat)); +for i=1:numel(spmmat) + load(spmmat{i},'SPM'); + SPMS{i} = SPM; +end + +matlabbatch{1}.spm.stats.fmri_spec.dir = cellstr(job.dir); +matlabbatch{1}.spm.stats.fmri_spec.timing.units = SPMS{1}.xBF.UNITS; +matlabbatch{1}.spm.stats.fmri_spec.timing.RT = SPMS{1}.xY.RT; +matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t = SPMS{1}.xBF.T; +matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t0 = SPMS{1}.xBF.T0; +switch SPMS{1}.xBF.name + case 'hrf' + matlabbatch{1}.spm.stats.fmri_spec.hrf.derivs = [0 0]; + case 'hrf (with time derivative)' + matlabbatch{1}.spm.stats.fmri_spec.hrf.derivs = [1 0]; + case 'hrf (with time and dispersion derivatives)' + matlabbatch{1}.spm.stats.fmri_spec.hrf.derivs = [1 1]; + case 'Fourier set' + matlabbatch{1}.spm.stats.fmri_spec.bases.fourier.length = SPMS{1}.xBF.length; + matlabbatch{1}.spm.stats.fmri_spec.bases.fourier.order = SPMS{1}.xBF.order; + case 'Fourier set (Hanning)' + matlabbatch{1}.spm.stats.fmri_spec.bases.fourier_han.length = SPMS{1}.xBF.length; + matlabbatch{1}.spm.stats.fmri_spec.bases.fourier_han.order = SPMS{1}.xBF.order; + case 'Gamma functions' + matlabbatch{1}.spm.stats.fmri_spec.bases.gamma.length = SPMS{1}.xBF.length; + matlabbatch{1}.spm.stats.fmri_spec.bases.gamma.order = SPMS{1}.xBF.order; + case 'Finite Impulse Response' + matlabbatch{1}.spm.stats.fmri_spec.bases.fir.length = SPMS{1}.xBF.length; + matlabbatch{1}.spm.stats.fmri_spec.bases.fir.order = SPMS{1}.xBF.order; +end +matlabbatch{1}.spm.stats.fmri_spec.volt = SPMS{1}.xBF.Volterra; +matlabbatch{1}.spm.stats.fmri_spec.global = SPMS{1}.xGX.iGXcalc; +if ~isempty(SPMS{1}.xM.VM) + matlabbatch{1}.spm.stats.fmri_spec.mask = cellstr(SPMS{1}.xM.VM.fname); % can be intersection +end +if strncmp('AR',SPMS{1}.xVi.form,2) + matlabbatch{1}.spm.stats.fmri_spec.cvi = 'AR(1)'; +else + matlabbatch{1}.spm.stats.fmri_spec.cvi = 'none'; +end + +k = 1; +for i=1:numel(SPMS) + n = cumsum([1 SPMS{i}.nscan]); + for j=1:numel(SPMS{i}.Sess) + matlabbatch{1}.spm.stats.fmri_spec.sess(k).scans = cellstr(SPMS{i}.xY.P(n(j):n(j+1)-1,:)); + for l=1:numel(SPMS{i}.Sess(j).U) + matlabbatch{1}.spm.stats.fmri_spec.sess(k).cond(l).name = SPMS{i}.Sess(j).U(l).name{1}; + matlabbatch{1}.spm.stats.fmri_spec.sess(k).cond(l).onset = SPMS{i}.Sess(j).U(l).ons; + matlabbatch{1}.spm.stats.fmri_spec.sess(k).cond(l).duration = SPMS{i}.Sess(j).U(l).dur; + o = 1; + for m=1:numel(SPMS{i}.Sess(j).U(l).P) + switch SPMS{i}.Sess(j).U(l).P(m).name + case 'time' + matlabbatch{1}.spm.stats.fmri_spec.sess(k).cond(l).tmod = SPMS{i}.Sess(j).U(l).P(m).h; + case 'none' + otherwise + matlabbatch{1}.spm.stats.fmri_spec.sess(k).cond(l).pmod(o).name = SPMS{i}.Sess(j).U(l).P(m).name; + matlabbatch{1}.spm.stats.fmri_spec.sess(k).cond(l).pmod(o).param = SPMS{i}.Sess(j).U(l).P(m).P; + matlabbatch{1}.spm.stats.fmri_spec.sess(k).cond(l).pmod(o).poly = SPMS{i}.Sess(j).U(l).P(m).h; + o = o + 1; + end + end + end + for l=1:numel(SPMS{i}.Sess(j).C.name) + matlabbatch{1}.spm.stats.fmri_spec.sess(k).regress(l).name = SPMS{i}.Sess(j).C.name{l}; + matlabbatch{1}.spm.stats.fmri_spec.sess(k).regress(l).val = SPMS{i}.Sess(j).C.C(:,l); + end + matlabbatch{1}.spm.stats.fmri_spec.sess(k).hpf = SPMS{i}.xX.K(j).HParam; + k = k + 1; + end +end +spm_jobman('run',matlabbatch); + +out.spmmat{1} = fullfile(job.dir{1},'SPM.mat'); + +% ===================================================================== +function dep = vout_ffx(job) +dep = cfg_dep; +dep.sname = 'SPM.mat File'; +dep.src_output = substruct('.','spmmat'); +dep.tgt_spec = cfg_findspec({{'filter','mat','strtype','e'}}); + +% ===================================================================== +function out = spm_local_mfx(job) +load(job.spmmat{1},'SPM'); +spm_mfx(SPM); +out.spmmat{1} = fullfile(fileparts(job.spmmat{1}),'mfx','SPM.mat'); + +% ===================================================================== +function dep = vout_mfx(job) +dep = cfg_dep; +dep.sname = 'SPM.mat File'; +dep.src_output = substruct('.','spmmat'); +dep.tgt_spec = cfg_findspec({{'filter','mat','strtype','e'}}); diff --git a/config/spm_cfg_ppi.m b/config/spm_cfg_ppi.m index 5c0927e..68d9908 100644 --- a/config/spm_cfg_ppi.m +++ b/config/spm_cfg_ppi.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: spm_cfg_ppi.m 3553 2009-11-11 12:34:37Z guillaume $ +% $Id: spm_cfg_ppi.m 4136 2010-12-09 22:22:28Z guillaume $ % --------------------------------------------------------------------- % spmmat Select SPM.mat @@ -45,11 +45,11 @@ con = cfg_entry; con.tag = 'u'; con.name = ' Input variables and contrast weights'; -con.help = {['Matrix of input variables and contrast weights.'... -'This is an [n x 3] matrix. The first column indexes SPM.Sess.U(i). ' ... -'The second column indexes the name of the input or cause, see ' ... -'SPM.Sess.U(i).name{j}. The third column is the contrast weight. ' ... -' Unless there are parametric effects the second column will generally ' ... +con.help = {['Matrix of input variables and contrast weights.',... +'This is an [n x 3] matrix. The first column indexes SPM.Sess.U(i). ',... +'The second column indexes the name of the input or cause, see ',... +'SPM.Sess.U(i).name{j}. The third column is the contrast weight. ',... +' Unless there are parametric effects the second column will generally ',... 'be a 1.']}; con.strtype = 'e'; con.num = [Inf 3]; @@ -96,7 +96,7 @@ name = cfg_entry; name.tag = 'name'; name.name = 'Name of PPI'; -name.help = {['Name of the PPI mat file that will be saved in the ' ... +name.help = {['Name of the PPI mat file that will be saved in the ',... 'same directory than the SPM.mat file. A ''PPI_'' prefix will be added.']}; name.strtype = 's'; name.num = [1 Inf]; diff --git a/config/spm_cfg_print.m b/config/spm_cfg_print.m index 36c1aef..6c68fe2 100644 --- a/config/spm_cfg_print.m +++ b/config/spm_cfg_print.m @@ -4,7 +4,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_print.m 1775 2008-06-02 09:18:18Z volkmar $ +% $Id: spm_cfg_print.m 4046 2010-08-26 15:12:57Z volkmar $ % --------------------------------------------------------------------- % print Printing @@ -113,19 +113,41 @@ opts.values{18}.ext = '.tif'; opts.def = @(val)spm_get_defaults('ui.print', val{:}); -fname = cfg_entry; -fname.tag = 'fname'; -fname.name = 'Print Filename'; +fname = cfg_entry; +fname.tag = 'fname'; +fname.name = 'Print Filename'; fname.strtype = 's'; -fname.val = {}; % explicitly unset this val -fname.help = {['Filename to print to. If this is set as a default - even ' ... - 'if it is set to an empty string - spm_print(''fname'') ' ... - 'will not print to file ''fname'', but to the standard SPM ' ... - 'print file.']}; +fname.val = {}; % explicitly unset this val +fname.help = {['Filename to print to. If this is set as a default - even ' ... + 'if it is set to an empty string - spm_print(''fname'') ' ... + 'will not print to file ''fname'', but to the standard SPM ' ... + 'print file.']}; -cfg_print = cfg_exbranch; -cfg_print.tag = 'print'; +figname = cfg_entry; +figname.tag = 'figname'; +figname.name = 'Figure Name'; +figname.strtype = 's'; +figname.val = {'Graphics'}; +figname.help = {['Figure to print. The figure will be determined by ' ... + 'calling spm_figure(''FindWin'', ...).']}; + +fighandle = cfg_entry; +fighandle.tag = 'fighandle'; +fighandle.name = 'Figure Handle'; +fighandle.strtype = 'r'; +fighandle.val = {}; % explicitly unset this val +fighandle.help = {['Figure to print. The value entered here must be a ' ... + 'figure handle. If it is a non-finite value (Inf/NaN), ' ... + 'the SPM Graphics/Help window is printed.']}; + +fig = cfg_choice; +fig.tag = 'fig'; +fig.name = 'Figure to print'; +fig.values = {figname, fighandle}; + +cfg_print = cfg_exbranch; +cfg_print.tag = 'print'; cfg_print.name = 'Print'; -cfg_print.val = {fname, opts}; +cfg_print.val = {fname, fig, opts}; cfg_print.prog = @spm_print; cfg_print.help = {'Print the Graphics/Help window.'}; diff --git a/config/spm_cfg_realign.m b/config/spm_cfg_realign.m index 3ec1905..c7594a1 100644 --- a/config/spm_cfg_realign.m +++ b/config/spm_cfg_realign.m @@ -4,9 +4,9 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_realign.m 3804 2010-03-31 16:16:21Z ged $ +% $Id: spm_cfg_realign.m 4152 2011-01-11 14:13:35Z volkmar $ -rev = '$Rev: 3804 $'; +rev = '$Rev: 4152 $'; % --------------------------------------------------------------------- % data Session % --------------------------------------------------------------------- @@ -130,11 +130,11 @@ weight = cfg_files; weight.tag = 'weight'; weight.name = 'Weighting'; +weight.val = {''}; weight.help = {'The option of providing a weighting image to weight each voxel of the reference image differently when estimating the realignment parameters. The weights are proportional to the inverses of the standard deviations. This would be used, for example, when there is a lot of extra-brain motion - e.g., during speech, or when there are serious artifacts in a particular region of the images.'}; weight.filter = 'image'; weight.ufilter = '.*'; weight.num = [0 1]; -weight.def = @(val)spm_get_defaults('realign.estimate.weight', val{:}); % --------------------------------------------------------------------- % eoptions Estimation Options % --------------------------------------------------------------------- diff --git a/config/spm_cfg_realignunwarp.m b/config/spm_cfg_realignunwarp.m index 6e2d1df..3d7c3ba 100644 --- a/config/spm_cfg_realignunwarp.m +++ b/config/spm_cfg_realignunwarp.m @@ -4,9 +4,9 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_realignunwarp.m 3804 2010-03-31 16:16:21Z ged $ +% $Id: spm_cfg_realignunwarp.m 4152 2011-01-11 14:13:35Z volkmar $ -rev = '$Rev: 3804 $'; +rev = '$Rev: 4152 $'; % --------------------------------------------------------------------- % scans Images % --------------------------------------------------------------------- @@ -159,11 +159,11 @@ weight = cfg_files; weight.tag = 'weight'; weight.name = 'Weighting'; +weight.val = {''}; weight.help = {'The option of providing a weighting image to weight each voxel of the reference image differently when estimating the realignment parameters. The weights are proportional to the inverses of the standard deviations. For example, when there is a lot of extra-brain motion - e.g., during speech, or when there are serious artifacts in a particular region of the images.'}; weight.filter = 'image'; weight.ufilter = '.*'; weight.num = [0 1]; -weight.def = @(val)spm_get_defaults('realign.estimate.weight', val{:}); % --------------------------------------------------------------------- % eoptions Estimation Options % --------------------------------------------------------------------- diff --git a/config/spm_cfg_st.m b/config/spm_cfg_st.m index 3b57c0e..81c27b0 100644 --- a/config/spm_cfg_st.m +++ b/config/spm_cfg_st.m @@ -3,7 +3,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_st.m 4005 2010-07-21 10:54:55Z guillaume $ +% $Id: spm_cfg_st.m 4269 2011-03-29 16:03:43Z guillaume $ % --------------------------------------------------------------------- % scans Session @@ -11,7 +11,7 @@ scans = cfg_files; scans.tag = 'scans'; scans.name = 'Session'; -scans.help = {'Select images to acquisition correct.'}; +scans.help = {'Select images to slice-time correct.'}; scans.filter = 'image'; scans.ufilter = '.*'; scans.num = [2 Inf]; @@ -30,7 +30,7 @@ nslices = cfg_entry; nslices.tag = 'nslices'; nslices.name = 'Number of Slices'; -nslices.help = {'Enter the number of slices'}; +nslices.help = {'Enter the number of slices.'}; nslices.strtype = 'n'; nslices.num = [1 1]; % --------------------------------------------------------------------- @@ -39,7 +39,7 @@ tr = cfg_entry; tr.tag = 'tr'; tr.name = 'TR'; -tr.help = {'Enter the TR in seconds'}; +tr.help = {'Enter the TR (in seconds).'}; tr.strtype = 'r'; tr.num = [1 1]; % --------------------------------------------------------------------- @@ -48,7 +48,7 @@ ta = cfg_entry; ta.tag = 'ta'; ta.name = 'TA'; -ta.help = {'The TA (in seconds) must be entered by the user. It is usually calculated as TR-(TR/nslices). You can simply enter this equation with the variables replaced by appropriate numbers.'}; +ta.help = {'Enter the TA (in seconds). It is usually calculated as TR-(TR/nslices). You can simply enter this equation with the variables replaced by appropriate numbers.'}; ta.strtype = 'e'; ta.num = [1 1]; % --------------------------------------------------------------------- @@ -90,7 +90,7 @@ prefix = cfg_entry; prefix.tag = 'prefix'; prefix.name = 'Filename Prefix'; -prefix.help = {'Specify the string to be prepended to the filenames of the smoothed image file(s). Default prefix is ''a''.'}; +prefix.help = {'Specify the string to be prepended to the filenames of the slice-time corrected image file(s). Default prefix is ''a''.'}; prefix.strtype = 's'; prefix.num = [1 Inf]; prefix.def = @(val)spm_get_defaults('slicetiming.prefix', val{:}); @@ -114,9 +114,11 @@ '' 'This correction assumes that the data are band-limited (i.e. there is no meaningful information present in the data at a frequency higher than that of the Nyquist). This assumption is support by the study of Josephs et al (1997, NeuroImage) that obtained event-related data at an effective TR of 166 msecs. No physio-logical signal change was present at frequencies higher than our typical Nyquist (0.25 HZ).' '' - 'Written by Darren Gitelman at Northwestern U., 1998. Based (in large part) on ACQCORRECT.PRO from Geoff Aguirre and Eric Zarahn at U. Penn.' + 'When using the slice timing correction it is very important that you input the correct slice order, and if there is any uncertainty then users are encouraged to work with their physicist to determine the actual slice acquisition order.' + '' + 'One can also consider augmenting the model by including the temporal derivative in the informed basis set instead of slice timing, which can account for +/- 1 second of changes in timing.' '' - 'Note that the authors of SPM do not generally suggest that this correction should be used, but the option is still retained for the few people who like to use it.' + 'Written by Darren Gitelman at Northwestern U., 1998. Based (in large part) on ACQCORRECT.PRO from Geoff Aguirre and Eric Zarahn at U. Penn.' }'; st.prog = @spm_run_st; st.vout = @vout; diff --git a/config/spm_cfg_voi.m b/config/spm_cfg_voi.m index 62863dc..e468062 100644 --- a/config/spm_cfg_voi.m +++ b/config/spm_cfg_voi.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: spm_cfg_voi.m 3919 2010-06-04 16:45:16Z guillaume $ +% $Id: spm_cfg_voi.m 4136 2010-12-09 22:22:28Z guillaume $ % ------------------------------------------------------------------------- % spmmat Select SPM.mat @@ -315,7 +315,7 @@ expression = cfg_entry; expression.tag = 'expression'; expression.name = 'Expression'; -expression.help = {['Expression to be evaluated, using i1, i2, ...' ... +expression.help = {['Expression to be evaluated, using i1, i2, ...',... 'and logical operators (&, |, ~)']}; expression.strtype = 's'; expression.num = [2 Inf]; @@ -358,8 +358,8 @@ name.tag = 'name'; name.name = 'Name of VOI'; name.help = {['Name of the VOI mat file that will be saved in the ' ... -'same directory than the SPM.mat file. A ''VOI_'' prefix will be added. '... -''... +'same directory than the SPM.mat file. A ''VOI_'' prefix will be added. ' ... +'' ... 'A binary NIfTI image of the VOI will also be saved.']}; name.strtype = 's'; name.num = [1 Inf]; diff --git a/config/spm_make_standalone.m b/config/spm_make_standalone.m new file mode 100644 index 0000000..a1d5f6a --- /dev/null +++ b/config/spm_make_standalone.m @@ -0,0 +1,104 @@ +function spm_make_standalone(outdir) +% Compile SPM as a standalone executable using the MATLAB compiler +% http://www.mathworks.com/products/compiler/ +% +% This will generate a standalone program, which can be run +% outside MATLAB, and therefore does not use up a MATLAB licence. +% +% On Windows: +% spm8_wxx.exe +% spm8_wxx.exe run +% +% On Linux/Mac: +% ./run_spm8.sh +% ./run_spm8.sh run +% +% The first command starts SPM in interactive mode with GUI. The second +% executes a batch file or starts the Batch Editor if empty. +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% John Ashburner +% $Id: spm_make_standalone.m 4017 2010-07-26 17:14:31Z guillaume $ + +%-Care of startup.m +%-------------------------------------------------------------------------- +% see http://www.mathworks.com/support/solutions/data/1-QXFMQ.html?1-QXFMQ +if exist('startup','file') + warning('A startup.m has been detected in %s.\n',... + fileparts(which('startup'))); +end + +if ~nargin, outdir = fullfile(spm('dir'),'..','spm_exec'); mkdir(outdir); end + +%========================================================================== +%-Static listing of SPM toolboxes +%========================================================================== +fid = fopen(fullfile(spm('dir'),'config','spm_cfg_static_tools.m'),'wt'); +fprintf(fid,'function values = spm_cfg_static_tools\n'); +fprintf(fid,... + '%% Static listing of all batch configuration files in the SPM toolbox folder\n'); +% create code to insert toolbox config +%-Toolbox autodetection +%-Get the list of toolbox directories +tbxdir = fullfile(spm('Dir'),'toolbox'); +d = dir(tbxdir); d = {d([d.isdir]).name}; +dd = regexp(d,'^\.'); +%(Beware, regexp returns an array if input cell array is of dim 0 or 1) +if ~iscell(dd), dd = {dd}; end +d = {'' d{cellfun('isempty',dd)}}; +ft = {}; +ftc = {}; +%-Look for '*_cfg_*.m' or '*_config_*.m' files in these directories +for i=1:length(d) + d2 = fullfile(tbxdir,d{i}); + di = dir(d2); di = {di(~[di.isdir]).name}; + f2 = regexp(di,'.*_cfg_.*\.m$'); + if ~iscell(f2), f2 = {f2}; end + fi = {di{~cellfun('isempty',f2)}}; + if ~isempty(fi) + ft = [ft(:); fi(:)]; + else + % try *_config_*.m files, if toolbox does not have '*_cfg_*.m' files + f2 = regexp(di,'.*_config_.*\.m$'); + if ~iscell(f2), f2 = {f2}; end + fi = {di{~cellfun('isempty',f2)}}; + ftc = [ftc(:); fi(:)]; + end; +end +if ~isempty(ft)||~isempty(ftc) + if isempty(ft) + ftstr = ''; + else + ft = cellfun(@(cft)strtok(cft,'.'),ft,'UniformOutput',false); + ftstr = sprintf('%s ', ft{:}); + end + if isempty(ftc) + ftcstr = ''; + else + ftc = cellfun(@(cftc)strtok(cftc,'.'),ftc,'UniformOutput',false); + ftcstr = sprintf('cfg_struct2cfg(%s) ', ftc{:}); + end + fprintf(fid,'values = {%s %s};\n', ftstr, ftcstr); +end +fclose(fid); + +%========================================================================== +%-Static listing of batch application initialisation files +%========================================================================== +cfg_util('dumpcfg'); + +%========================================================================== +%-Duplicate Contents.m in Contents.txt for use in spm('Ver') +%========================================================================== +sts = copyfile(fullfile(spm('Dir'),'Contents.m'),... + fullfile(spm('Dir'),'Contents.txt')); +if ~sts, warning('Copy of Contents.m failed.'); end + +%========================================================================== +%-Compilation +%========================================================================== +mcc('-m', '-C', '-v', '-o',lower(spm('Ver')), 'spm_standalone.m',... + '-d',outdir,... + '-N','-p',fullfile(matlabroot,'toolbox','signal'),... + '-a',spm('Dir')) diff --git a/config/spm_run_bms_dcm.m b/config/spm_run_bms_dcm.m index 0c26527..c6876f9 100644 --- a/config/spm_run_bms_dcm.m +++ b/config/spm_run_bms_dcm.m @@ -17,7 +17,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % CC Chen & Maria Joao Rosa -% $Id: spm_run_bms_dcm.m 3955 2010-06-29 17:26:29Z maria $ +% $Id: spm_run_bms_dcm.m 4229 2011-03-04 15:01:34Z maria $ % input % ------------------------------------------------------------------------- @@ -53,7 +53,8 @@ if data_se load(job.sess_dcm{1}(1).mod_dcm{1}) else - error('Plase specify DCM.mat files to do BMA!') + spm('alert','Please specify DCM.mat files or model_space.mat to do BMA!','Error'); + return end end @@ -74,7 +75,8 @@ disp('Loading model space') load(job.model_sp{1}); if ~exist('subj','var') - error('Incorrect model space file! File must contain ''subj'' structure.') + spm('alert','Incorrect model space file! File must contain ''subj'' structure.','Error'); + return end end end @@ -110,7 +112,7 @@ ns = size(job.sess_dcm,2); % No of Subjects nsess = size(job.sess_dcm{1},2); % No of sessions nm = size(job.sess_dcm{1}(1).mod_dcm,1); % No of Models - fname_msp = [job.dir{1} 'model_space.mat']; + fname_msp = fullfile(job.dir{1},'model_space.mat'); end F = zeros(ns,nm); @@ -118,7 +120,7 @@ % Check if No of models > 2 if nm < 2 - msgbox('Please select more than one file') + spm('alert','Please select more than one file','Error'); return end @@ -215,16 +217,16 @@ failind = find(max(abs(diff(ID)),[],1) > eps); if ~isempty(failind) out.files{1} = []; - msgbox(['Error: the models for subject ' num2str(k) ... - ' session(s) ' num2str(failind) ' were not fitted to the same data.']); + str_error = ['The models for subject ' num2str(k) ... + ' session(s) ' num2str(failind) ' were not fitted to the same data.']; + spm('alert',str_error,'Error'); return end end else out.files{1} = []; - msgbox('Error: the number of sessions/models should be the same for all subjects!') - return - + spm('alert','The number of sessions/models should be the same for all subjects!','Error'); + return end end @@ -253,8 +255,9 @@ m_indx = 1:nm; if nfam ~= npart || npart == 1 || maxpart > npart - error('Invalid family file!') + spm('alert','Invalid family file!','Error'); out.files{1} = []; + return end else do_family = 0; @@ -285,7 +288,7 @@ nmodfam = length(m_indx); if nfam ~= npart || npart == 1 || maxpart > npart || nmodfam > nm - error('Invalid family!') + spm('alert','Invalid family!','Error'); out.files{1} = []; return end @@ -325,7 +328,8 @@ indx = find(family.partition==bma_fam); post = model.post(indx); else - error('Incorrect family for BMA!'); + spm('alert','Incorrect family for BMA!','Error'); + return end end end @@ -349,8 +353,8 @@ if exist(fullfile(job.dir{1},'BMS.mat'),'file') load(fname); if isfield(BMS,'DCM') && isfield(BMS.DCM,'ffx') - str = { 'Warning: existing BMS.mat file has been over-written!'}; - msgbox(str) + spm('alert','Existing BMS.mat file has been over-written!',... + 'Warning'); end end BMS.DCM.ffx.data = fname_msp; @@ -362,7 +366,7 @@ BMS.DCM.ffx.bma = bma; disp('Saving BMS.mat file...') - if spm_matlab_version_chk('7') >= 0 + if spm_check_version('matlab','7') >= 0 save(fname,'-V6','BMS'); else save(fname,'BMS'); @@ -412,7 +416,8 @@ indx = find(family.partition==bma_fam); post = model.g_post(:,indx); else - error('Incorrect family for BMA!'); + spm('alert','Incorrect family for BMA!','Error'); + return end end end @@ -435,8 +440,8 @@ if exist(fullfile(job.dir{1},'BMS.mat'),'file') load(fname); if isfield(BMS,'DCM') && isfield(BMS.DCM,'rfx') - str = { 'Warning: existing BMS.mat file has been over-written!'}; - msgbox(str) + spm('alert','Existing BMS.mat file has been over-written!',... + 'Warning'); end end BMS.DCM.rfx.data = fname_msp; @@ -448,7 +453,7 @@ BMS.DCM.rfx.bma = bma; disp('Saving BMS.mat file...') - if spm_matlab_version_chk('7') >= 0 + if spm_check_version('matlab','7') >= 0 save(fname,'-V6','BMS'); else save(fname,'BMS'); @@ -461,7 +466,7 @@ % ------------------------------------------------------------------------- if ~ld_msp && data_se && ~ld_f disp('Saving model space...') - if spm_matlab_version_chk('7') >= 0 + if spm_check_version('matlab','7') >= 0 save(fname_msp,'-V6','subj'); else save(fname_msp,'subj'); diff --git a/config/spm_run_bms_dcm_vis.m b/config/spm_run_bms_dcm_vis.m index 1b84ec2..2cde943 100644 --- a/config/spm_run_bms_dcm_vis.m +++ b/config/spm_run_bms_dcm_vis.m @@ -4,10 +4,10 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Chun-Chuan Chen and Maria Joao Rosa -% $Id: spm_run_bms_dcm_vis.m 3465 2009-10-14 15:14:29Z guillaume $ +% $Id: spm_run_bms_dcm_vis.m 4136 2010-12-09 22:22:28Z guillaume $ -if isempty(job.file{1})==1 - fname = spm_select([1 1],'^BMS.mat$','select BMS.mat file'); +if ~exist('job','var') || isempty(job.file{1}) + fname = spm_select([1 1],'^BMS\.mat$','select BMS.mat file'); load(fname); else load(job.file{1}); diff --git a/config/spm_run_coreg_estimate.m b/config/spm_run_coreg_estimate.m index e6f2908..141f14b 100644 --- a/config/spm_run_coreg_estimate.m +++ b/config/spm_run_coreg_estimate.m @@ -6,24 +6,26 @@ % job - harvested job data structure (see matlabbatch help) % Output: % out - computation results, usually a struct variable. -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_coreg_estimate.m 2187 2008-09-25 11:50:50Z volkmar $ +% $Id: spm_run_coreg_estimate.m 4161 2011-01-13 13:44:37Z volkmar $ job = varargin{1}; -%disp(job); -%disp(job.eoptions); +if isempty(job.other{1}) + job.other = {}; +end -x = spm_coreg(strvcat(job.ref), strvcat(job.source),job.eoptions); -M = inv(spm_matrix(x)); -PO = strvcat(strvcat(job.source),strvcat(job.other)); -MM = zeros(4,4,size(PO,1)); -for j=1:size(PO,1), - MM(:,:,j) = spm_get_space(deblank(PO(j,:))); -end; -for j=1:size(PO,1), - spm_get_space(deblank(PO(j,:)), M*MM(:,:,j)); -end; -out.cfiles = cellstr(PO); -return; +x = spm_coreg(char(job.ref), char(job.source), job.eoptions); + +M = spm_matrix(x); +PO = [job.source(:); job.other(:)]; +MM = zeros(4,4,numel(PO)); +for j=1:numel(PO) + MM(:,:,j) = spm_get_space(PO{j}); +end +for j=1:numel(PO) + spm_get_space(PO{j}, M\MM(:,:,j)); +end + +out.cfiles = PO; diff --git a/config/spm_run_coreg_estwrite.m b/config/spm_run_coreg_estwrite.m index ae36ccb..7ce4845 100644 --- a/config/spm_run_coreg_estwrite.m +++ b/config/spm_run_coreg_estwrite.m @@ -9,7 +9,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_coreg_estwrite.m 2485 2008-11-21 13:31:24Z john $ +% $Id: spm_run_coreg_estwrite.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; if isempty(job.other{1}) @@ -20,30 +20,31 @@ error('This is not supposed to work.'); end -x = spm_coreg(strvcat(job.ref), strvcat(job.source),job.eoptions); +x = spm_coreg(char(job.ref), char(job.source),job.eoptions); if numel(job.other)>0, - M = inv(spm_matrix(x)); - PO = {job.source{:} job.other{:}}; + M = spm_matrix(x); + PO = [job.source(:); job.other(:)]; MM = zeros(4,4,numel(PO)); for j=1:numel(PO), MM(:,:,j) = spm_get_space(PO{j}); end for j=1:numel(PO), - spm_get_space(PO{j}, M*MM(:,:,j)); + spm_get_space(PO{j}, M\MM(:,:,j)); end else PO = job.source; + MM = zeros(4,4,numel(PO)); for j=1:numel(PO) MM(:,:,j) = spm_get_space(PO{j}); end for j=1:numel(PO), - M = inv(spm_matrix(x(j,:))); - spm_get_space(PO{j}, M*MM(:,:,j)); + M = spm_matrix(x(j,:)); + spm_get_space(PO{j}, M\MM(:,:,j)); end end -P = strvcat(job.ref{:},job.source{:},job.other{:}); +P = char(job.ref{:},job.source{:},job.other{:}); flags.mask = job.roptions.mask; flags.mean = 0; flags.interp = job.roptions.interp; @@ -53,7 +54,7 @@ spm_reslice(P,flags); -out.cfiles = {job.source{:} job.other{:}}; +out.cfiles = [job.source(:); job.other(:)]; out.rfiles = cell(size(out.cfiles)); for i=1:numel(out.cfiles), [pth,nam,ext,num] = spm_fileparts(out.cfiles{i}); diff --git a/config/spm_run_coreg_reslice.m b/config/spm_run_coreg_reslice.m index c14121b..b7c1339 100644 --- a/config/spm_run_coreg_reslice.m +++ b/config/spm_run_coreg_reslice.m @@ -9,11 +9,11 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_coreg_reslice.m 2312 2008-10-07 17:02:46Z volkmar $ +% $Id: spm_run_coreg_reslice.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; -P = strvcat(strvcat(job.ref),strvcat(job.source)); +P = char([job.ref(:);job.source(:)]); flags.mask = job.roptions.mask; flags.mean = 0; flags.interp = job.roptions.interp; diff --git a/config/spm_run_factorial_design.m b/config/spm_run_factorial_design.m index 4d31a81..1a7e965 100644 --- a/config/spm_run_factorial_design.m +++ b/config/spm_run_factorial_design.m @@ -8,7 +8,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_run_factorial_design.m 3860 2010-05-04 15:59:25Z guillaume $ +% $Id: spm_run_factorial_design.m 4185 2011-02-01 18:46:18Z guillaume $ %-------------------------------------------------------------------------- % This function configures the design matrix (describing the general @@ -357,8 +357,8 @@ I(:,3) = kron(ones(Npairs,1),[1 2]'); I(:,4) = I(:,1); - [H,Hnames] = spm_DesMtx(I(:,2),'-','Subject'); - [B,Bnames] = spm_DesMtx(I(:,3),'-','Condition'); + [B,Bnames] = spm_DesMtx(I(:,2),'-','Subject'); + [H,Hnames] = spm_DesMtx(I(:,3),'-','Condition'); % Names and levels SPM.factor(1).name = 'Subject'; @@ -397,11 +397,10 @@ SPM.factor(1).variance = 0; SPM.factor(1).dept = 0; - H = []; Hnames = []; if job.des.mreg.incint==0 - B = []; Bnames = ''; + H = []; Hnames = ''; else - [B,Bnames] = spm_DesMtx(I(:,2),'-','mean'); + [H,Hnames] = spm_DesMtx(I(:,2),'-','mean'); end for i=1:length(job.des.mreg.mcov) @@ -446,33 +445,33 @@ DesName = 'ANOVA - within subject'; - anovaw=job.des.anovaw; - anovaw.fac(1).name='Subject'; - anovaw.fac(1).dept=0; - anovaw.fac(1).variance=0; - anovaw.fac(1).gmsca=0; - anovaw.fac(1).ancova=0; + anovaw = job.des.anovaw; + anovaw.fac(1).name = 'Subject'; + anovaw.fac(1).dept = 0; + anovaw.fac(1).variance = 0; + anovaw.fac(1).gmsca = 0; + anovaw.fac(1).ancova = 0; - anovaw.fac(2).name='Groups'; - anovaw.fac(2).dept=job.des.anovaw.dept; - anovaw.fac(2).variance=job.des.anovaw.variance; - anovaw.fac(2).gmsca=job.des.anovaw.gmsca; - anovaw.fac(2).ancova=job.des.anovaw.ancova; + anovaw.fac(2).name = 'Groups'; + anovaw.fac(2).dept = job.des.anovaw.dept; + anovaw.fac(2).variance = job.des.anovaw.variance; + anovaw.fac(2).gmsca = job.des.anovaw.gmsca; + anovaw.fac(2).ancova = job.des.anovaw.ancova; - anovaw.fsuball.fsubject=anovaw.fsubject; + anovaw.fsuball.fsubject = anovaw.fsubject; % Main effect of subject and group - anovaw.maininters{1}.fmain.fnum=1; - anovaw.maininters{2}.fmain.fnum=2; + anovaw.maininters{1}.fmain.fnum = 1; + anovaw.maininters{2}.fmain.fnum = 2; [I,P,job.cov] = spm_design_within_subject(anovaw,job.cov); - [H,Hnames] = spm_design_flexible(anovaw,I); + [H,Hnames,B,Bnames] = spm_design_flexible(anovaw,I); - for i=1:2, - SPM.factor(i)=anovaw.fac(i); + for i=1:2 + SPM.factor(i) = anovaw.fac(i); end - SPM.factor(1).levels = length(job.des.anovaw.fsubject); + SPM.factor(1).levels = length(job.des.anovaw.fsubject); %-Full Factorial Design %====================================================================== @@ -526,7 +525,7 @@ end - [H,Hnames] = spm_design_flexible(job.des.fblock,I); + [H,Hnames,B,Bnames] = spm_design_flexible(job.des.fblock,I); for i=1:nf % Names and levels @@ -1009,10 +1008,10 @@ %-------------------------------------------------------------------------- fprintf('%-40s: ','Saving SPM configuration') %-# -if spm_matlab_version_chk('7') >= 0 - save('SPM', 'SPM', '-V6'); +if spm_check_version('matlab','7') >= 0 + save('SPM.mat', 'SPM', '-V6'); else - save('SPM', 'SPM'); + save('SPM.mat', 'SPM'); end fprintf('%30s\n','...SPM.mat saved') %-# diff --git a/config/spm_run_fmri_data.m b/config/spm_run_fmri_data.m index 0ee139c..d128820 100644 --- a/config/spm_run_fmri_data.m +++ b/config/spm_run_fmri_data.m @@ -10,7 +10,7 @@ %_________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_fmri_data.m 3756 2010-03-05 18:43:37Z guillaume $ +% $Id: spm_run_fmri_data.m 4185 2011-02-01 18:46:18Z guillaume $ spm('defaults','FMRI'); @@ -36,11 +36,11 @@ %-Save SPM.mat %------------------------------------------------------------------------- fprintf('%-40s: ','Saving SPM configuration') %-# -if spm_matlab_version_chk('7') >= 0 - save('SPM','-V6','SPM'); +if spm_check_version('matlab','7') >= 0 + save('SPM.mat','-V6','SPM'); else - save('SPM','SPM'); -end; + save('SPM.mat','SPM'); +end fprintf('%30s\n','...SPM.mat saved') %-# diff --git a/config/spm_run_fmri_design.m b/config/spm_run_fmri_design.m index 737ca59..c924f39 100644 --- a/config/spm_run_fmri_design.m +++ b/config/spm_run_fmri_design.m @@ -10,7 +10,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_fmri_design.m 3692 2010-01-21 21:43:31Z guillaume $ +% $Id: spm_run_fmri_design.m 4185 2011-02-01 18:46:18Z guillaume $ original_dir = pwd; @@ -302,11 +302,11 @@ %-Save SPM.mat %------------------------------------------------------------------------- fprintf('%-40s: ','Saving SPM configuration') %-# -if spm_matlab_version_chk('7') >= 0 - save('SPM','-V6','SPM'); +if spm_check_version('matlab','7') >= 0 + save('SPM.mat','-V6','SPM'); else - save('SPM','SPM'); -end; + save('SPM.mat','SPM'); +end fprintf('%30s\n','...SPM.mat saved') %-# diff --git a/config/spm_run_fmri_est.m b/config/spm_run_fmri_est.m index 5e617f1..41a1389 100644 --- a/config/spm_run_fmri_est.m +++ b/config/spm_run_fmri_est.m @@ -10,7 +10,7 @@ %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_fmri_est.m 3691 2010-01-20 17:08:30Z guillaume $ +% $Id: spm_run_fmri_est.m 4022 2010-07-28 12:50:20Z guillaume $ %-Load SPM.mat file %-------------------------------------------------------------------------- @@ -70,7 +70,7 @@ for r=1:size(Fcon,1) con = Fcon(r,:); str = cons(i).name; - if ~isempty(strmatch('Interaction',str)) + if strncmp('Interaction',str,11) name = ['Positive ',str,'_',int2str(r)]; else sp1 = find(isspace(str), 1); diff --git a/config/spm_run_fmri_spec.m b/config/spm_run_fmri_spec.m index 22efede..5760ee6 100644 --- a/config/spm_run_fmri_spec.m +++ b/config/spm_run_fmri_spec.m @@ -10,7 +10,7 @@ %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_fmri_spec.m 3757 2010-03-08 11:41:53Z guillaume $ +% $Id: spm_run_fmri_spec.m 4185 2011-02-01 18:46:18Z guillaume $ original_dir = pwd; @@ -308,10 +308,10 @@ %-Save SPM.mat %-------------------------------------------------------------------------- fprintf('%-40s: ','Saving SPM configuration') %-# -if spm_matlab_version_chk('7') >= 0 - save('SPM','-V6','SPM'); +if spm_check_version('matlab','7') >= 0 + save('SPM.mat','-V6','SPM'); else - save('SPM','SPM'); + save('SPM.mat','SPM'); end; fprintf('%30s\n','...SPM.mat saved') %-# diff --git a/config/spm_run_minc.m b/config/spm_run_minc.m index f0bd0b6..4fd14ed 100644 --- a/config/spm_run_minc.m +++ b/config/spm_run_minc.m @@ -1,4 +1,4 @@ -function out = convert_minc(job) +function out = spm_run_minc(job) % SPM job execution function % takes a harvested job data structure and call SPM functions to perform % computations on the data. @@ -9,7 +9,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_minc.m 3691 2010-01-20 17:08:30Z guillaume $ +% $Id: spm_run_minc.m 4136 2010-12-09 22:22:28Z guillaume $ if job.opts.ext(1) ~= '.', job.opts.ext = ['.' job.opts.ext]; end out.files = cell(size(job.data)); diff --git a/config/spm_run_normalise_estimate.m b/config/spm_run_normalise_estimate.m index b39e701..3ddc5bd 100644 --- a/config/spm_run_normalise_estimate.m +++ b/config/spm_run_normalise_estimate.m @@ -9,23 +9,17 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_normalise_estimate.m 2335 2008-10-13 18:49:25Z christophe $ +% $Id: spm_run_normalise_estimate.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; -o = job.eoptions; -eflags = struct(... - 'smosrc', o.smosrc,... - 'smoref', o.smoref,... - 'regtype',o.regtype,... - 'cutoff', o.cutoff,... - 'nits', o.nits,... - 'reg', o.reg); +eflags = rmfield(job.eoptions,{'template','weight'}); +out = repmat(struct('params',{''}),size(job.subj)); for i=1:numel(job.subj), - [pth,nam,ext,ind] = spm_fileparts(strvcat(job.subj(i).source{:})); - out(i).params{1} = fullfile(pth,[nam,'_sn.mat']); - spm_normalise(strvcat(job.eoptions.template{:}),... - strvcat(job.subj(i).source{:}), out(i).params{1},... - strvcat(job.eoptions.weight), strvcat(job.subj(i).wtsrc), eflags); + [pth,nam] = spm_fileparts(char(job.subj(i).source)); + out(i).params = {fullfile(pth,[nam,'_sn.mat'])}; + spm_normalise(char(job.eoptions.template),... + char(job.subj(i).source), out(i).params{1},... + char(job.eoptions.weight), char(job.subj(i).wtsrc), eflags); end; return; diff --git a/config/spm_run_normalise_estwrite.m b/config/spm_run_normalise_estwrite.m index 04358bb..9188115 100644 --- a/config/spm_run_normalise_estwrite.m +++ b/config/spm_run_normalise_estwrite.m @@ -9,33 +9,20 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_normalise_estwrite.m 2312 2008-10-07 17:02:46Z volkmar $ +% $Id: spm_run_normalise_estwrite.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; -o = job.eoptions; -eflags = struct(... - 'smosrc', o.smosrc,... - 'smoref', o.smoref,... - 'regtype',o.regtype,... - 'cutoff', o.cutoff,... - 'nits', o.nits,... - 'reg', o.reg); -o = job.roptions; -rflags = struct(... - 'preserve',o.preserve,... - 'bb', o.bb,... - 'vox', o.vox,... - 'interp', o.interp,... - 'wrap', o.wrap,... - 'prefix', o.prefix); +eflags = rmfield(job.eoptions,{'weight','template'}); +rflags = job.roptions; +out = repmat(struct('params',{''},'files',{''}),size(job.subj)); for i=1:numel(job.subj), - [ pth,nam ] = spm_fileparts(deblank(job.subj(i).source{:})); - out(i).params{1} = fullfile(pth,[nam,'_sn.mat']); - spm_normalise(strvcat(job.eoptions.template{:}),... - strvcat(job.subj(i).source{:}), out(i).params{1},... - strvcat(job.eoptions.weight), strvcat(job.subj(i).wtsrc), eflags); - spm_write_sn(strvcat(job.subj(i).resample{:}), out(i).params{1}, rflags); + [ pth,nam ] = spm_fileparts(char(job.subj(i).source)); + out(i).params = {fullfile(pth,[nam,'_sn.mat'])}; + spm_normalise(char(job.eoptions.template),... + char(job.subj(i).source), out(i).params{1},... + char(job.eoptions.weight), char(job.subj(i).wtsrc), eflags); + spm_write_sn(char(job.subj(i).resample), out(i).params{1}, rflags); out(i).files = cell(size(job.subj(i).resample)); for j=1:numel(job.subj(i).resample), [pth,nam,ext,num] = spm_fileparts(job.subj(i).resample{j}); diff --git a/config/spm_run_normalise_write.m b/config/spm_run_normalise_write.m index c4e94c3..8f08321 100644 --- a/config/spm_run_normalise_write.m +++ b/config/spm_run_normalise_write.m @@ -9,21 +9,15 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_normalise_write.m 2312 2008-10-07 17:02:46Z volkmar $ +% $Id: spm_run_normalise_write.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; -o = job.roptions; -rflags = struct(... - 'preserve',o.preserve,... - 'bb', o.bb,... - 'vox', o.vox,... - 'interp', o.interp,... - 'wrap', o.wrap,... - 'prefix', o.prefix); +rflags = job.roptions; +out = repmat(struct('files',{''}),size(job.subj)); for i=1:numel(job.subj), - spm_write_sn(strvcat(job.subj(i).resample{:}),... - strvcat(job.subj(i).matname{:}),rflags); + spm_write_sn(char(job.subj(i).resample),... + char(job.subj(i).matname),rflags); res = job.subj(i).resample; out(i).files = cell(size(res)); for j=1:numel(res), diff --git a/config/spm_run_preproc.m b/config/spm_run_preproc.m index f25e0d9..2b812b2 100644 --- a/config/spm_run_preproc.m +++ b/config/spm_run_preproc.m @@ -6,14 +6,14 @@ % job - harvested job data structure (see matlabbatch help) % Output: % out - computation results, usually a struct variable. -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_preproc.m 2312 2008-10-07 17:02:46Z volkmar $ +% $Id: spm_run_preproc.m 4185 2011-02-01 18:46:18Z guillaume $ -job.opts.tpm = strvcat(job.opts.tpm{:}); +job.opts.tpm = char(job.opts.tpm); if isfield(job.opts,'msk'), - job.opts.msk = strvcat(job.opts.msk{:}); + job.opts.msk = char(job.opts.msk); end; for i=1:numel(job.data), res = spm_preproc(job.data{i},job.opts); @@ -50,20 +50,19 @@ end; end; return; -%------------------------------------------------------------------------ -%------------------------------------------------------------------------ +%========================================================================== function savefields(fnam,p) -if length(p)>1, error('Can''t save fields.'); end; +if length(p)>1, error('Can''t save fields.'); end fn = fieldnames(p); -if numel(fn)==0, return; end; -for i=1:length(fn), +if numel(fn)==0, return; end +for i=1:length(fn) eval([fn{i} '= p.' fn{i} ';']); -end; -if spm_matlab_version_chk('7') >= 0 +end +if spm_check_version('matlab','7') >= 0 save(fnam,'-V6',fn{:}); else save(fnam,fn{:}); -end; +end return; diff --git a/config/spm_run_realign_estimate.m b/config/spm_run_realign_estimate.m index 59a674b..dcdfbff 100644 --- a/config/spm_run_realign_estimate.m +++ b/config/spm_run_realign_estimate.m @@ -9,18 +9,18 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_realign_estimate.m 1185 2008-03-04 16:31:21Z volkmar $ +% $Id: spm_run_realign_estimate.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; -P = {}; +P = cell(size(job.data)); for i=1:length(job.data), - P{i} = strvcat(job.data{i}); + P{i} = char(job.data{i}); end; flags.quality = job.eoptions.quality; flags.fwhm = job.eoptions.fwhm; flags.sep = job.eoptions.sep; flags.rtm = job.eoptions.rtm; -flags.PW = strvcat(job.eoptions.weight); +flags.PW = char(job.eoptions.weight); flags.interp = job.eoptions.interp; flags.wrap = job.eoptions.wrap; spm_realign(P,flags); diff --git a/config/spm_run_realign_estwrite.m b/config/spm_run_realign_estwrite.m index 1741ea7..43bcc2b 100644 --- a/config/spm_run_realign_estwrite.m +++ b/config/spm_run_realign_estwrite.m @@ -9,18 +9,18 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_realign_estwrite.m 1185 2008-03-04 16:31:21Z volkmar $ +% $Id: spm_run_realign_estwrite.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; -P = {}; -for i=1:length(job.data), - P{i} = strvcat(job.data{i}); +P = cell(size(job.data)); +for i=1:numel(job.data), + P{i} = char(job.data{i}); end; flags.quality = job.eoptions.quality; flags.fwhm = job.eoptions.fwhm; flags.sep = job.eoptions.sep; flags.rtm = job.eoptions.rtm; -flags.PW = strvcat(job.eoptions.weight); +flags.PW = char(job.eoptions.weight); flags.interp = job.eoptions.interp; flags.wrap = job.eoptions.wrap; spm_realign(P,flags); @@ -30,11 +30,10 @@ out.sess(i).rpfile{1} = fullfile(pth, sprintf('rp_%s.txt', nam)); end; -P = strvcat(P); +P = char(P); flags.mask = job.roptions.mask; -flags.mean = job.roptions.which(2); flags.interp = job.roptions.interp; -flags.which = job.roptions.which(1); +flags.which = job.roptions.which; flags.wrap = job.roptions.wrap; flags.prefix = job.roptions.prefix; spm_reslice(P,flags); diff --git a/config/spm_run_realign_reslice.m b/config/spm_run_realign_reslice.m index f28f478..0ec2c7c 100644 --- a/config/spm_run_realign_reslice.m +++ b/config/spm_run_realign_reslice.m @@ -9,14 +9,13 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_realign_reslice.m 1185 2008-03-04 16:31:21Z volkmar $ +% $Id: spm_run_realign_reslice.m 4152 2011-01-11 14:13:35Z volkmar $ job = varargin{1}; -P = strvcat(job.data); +P = char(job.data); flags.mask = job.roptions.mask; -flags.mean = job.roptions.which(2); flags.interp = job.roptions.interp; -flags.which = job.roptions.which(1); +flags.which = job.roptions.which; flags.wrap = job.roptions.wrap; flags.prefix = job.roptions.prefix; spm_reslice(P,flags); diff --git a/config/spm_run_realignunwarp.m b/config/spm_run_realignunwarp.m index 2194a35..875dc96 100644 --- a/config/spm_run_realignunwarp.m +++ b/config/spm_run_realignunwarp.m @@ -10,7 +10,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Darren R. Gitelman -% $Id: spm_run_realignunwarp.m 2337 2008-10-14 14:16:54Z volkmar $ +% $Id: spm_run_realignunwarp.m 4185 2011-02-01 18:46:18Z guillaume $ job = varargin{1}; @@ -21,7 +21,7 @@ flags.fwhm = job.eoptions.fwhm; flags.sep = job.eoptions.sep; flags.rtm = job.eoptions.rtm; -flags.PW = strvcat(job.eoptions.weight); +flags.PW = char(job.eoptions.weight); flags.interp = job.eoptions.einterp; flags.wrap = job.eoptions.ewrap; @@ -65,9 +65,10 @@ % assemble files %----------------------------------------------------------------------- -P = {}; +P = cell(size(job.data)); +sfP = cell(size(job.data)); for i = 1:numel(job.data) - P{i} = strvcat(job.data(i).scans{:}); + P{i} = char(job.data(i).scans{:}); if ~isempty(job.data(i).pmscan) sfP{i} = job.data(i).pmscan{1}; else @@ -91,7 +92,7 @@ [path,name] = fileparts(P{i}(1,:)); out.sess(i).dsfile{1} = fullfile(path,[name '_uw.mat']); - if spm_matlab_version_chk('7') >= 0 + if spm_check_version('matlab','7') >= 0 save(out.sess(i).dsfile{1},'-V6','ds'); else save(out.sess(i).dsfile{1},'ds'); diff --git a/config/spm_run_reorient.m b/config/spm_run_reorient.m index 4551263..fcaa2d2 100644 --- a/config/spm_run_reorient.m +++ b/config/spm_run_reorient.m @@ -9,7 +9,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_reorient.m 3130 2009-05-18 14:41:31Z volkmar $ +% $Id: spm_run_reorient.m 4177 2011-01-27 14:35:32Z volkmar $ job = varargin{1}; if isfield(job.transform,'transprm') @@ -28,7 +28,7 @@ for k = 1:numel(job.srcfiles) V = spm_vol(job.srcfiles{k}); X = spm_read_vols(V); - [p n e v] = spm_fileparts(V.fname) + [p n e v] = spm_fileparts(V.fname); V.mat = job.transform.transM*V.mat; V.fname = fullfile(p, [job.prefix n e v]); spm_write_vol(V,X); diff --git a/config/spm_run_voi.m b/config/spm_run_voi.m index f7cbe36..3d84563 100644 --- a/config/spm_run_voi.m +++ b/config/spm_run_voi.m @@ -10,7 +10,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: spm_run_voi.m 3780 2010-03-15 17:15:00Z guillaume $ +% $Id: spm_run_voi.m 4269 2011-03-29 16:03:43Z guillaume $ fprintf('## Note: this VOI facility is in a beta version. ##\n'); fprintf('## Interface and features might change in the future. ##\n'); @@ -65,7 +65,9 @@ xSPM.XYZ = XYZ; xSPM.M = SPM.xVol.M; % irrelevant here +if ~isempty(xY.Ic), cwd = pwd; cd(SPM.swd); end % to find beta images [Y,xY] = spm_regions(xSPM,SPM,[],xY); +if ~isempty(xY.Ic), cd(cwd); end %-Export results %-------------------------------------------------------------------------- @@ -185,7 +187,8 @@ error('The SPM index does not correspond to a Thresholded SPM ROI.'); end [mySPM, xSPM] = getSPM(job.roi{m}.spm); -XYZ = SPM.xVol.iM(1:3,:)*[xSPM.XYZmm;ones(1,size(xSPM.XYZmm,2))]; +XYZmm = xSPM.XYZmm; +XYZ = SPM.xVol.iM(1:3,:)*[XYZmm;ones(1,size(XYZmm,2))]; Z = xSPM.Z; if ~isempty(e) R = spm_sample_vol(uint8(roi_eval(voi,e)), ... @@ -194,7 +197,7 @@ XYZmm = xSPM.XYZmm(:,R); Z = xSPM.Z(R); end -[N Z M A] = spm_max(Z,XYZ); +[N, Z, M] = spm_max(Z,XYZ); if isempty(Z) warning('No voxel survived. Default to user-specified centre.'); return @@ -207,8 +210,8 @@ nc = SPM.xVol.M(1:3,:)*[M(:,j);1]; str = sprintf(['centre moved to global maxima ' str],nc); case 'local' - XYZ = SPM.xVol.M(1:3,:)*[M;ones(1,size(M,2))]; - nc = spm_XYZreg('NearestXYZ',c,XYZ); + XYZmm = SPM.xVol.M(1:3,:)*[M;ones(1,size(M,2))]; + nc = spm_XYZreg('NearestXYZ',c,XYZmm); str = sprintf(['centre moved from ' str ' to ' str],c,nc); case 'supra' nc = spm_XYZreg('NearestXYZ',c,XYZmm); diff --git a/man/FieldMap/fieldmap.tex b/man/FieldMap/fieldmap.tex index e5f7793..ba3e28c 100644 --- a/man/FieldMap/fieldmap.tex +++ b/man/FieldMap/fieldmap.tex @@ -7,18 +7,310 @@ \section{Introduction} \url{http://www.fil.ion.ucl.ac.uk/spm/software/spm5/}\\ FieldMap Version 1.1 for SPM2 can be downloaded from \url{http://www.fil.ion.ucl.ac.uk/spm/toolbox/fieldmap/}} - for creating unwrapped field maps that can be used to do geometric distortion correction of EPI images \cite{jezzard95,jenkinson03,chloe_distortion,chloe_distortion2,ja_geometric}. The toolbox can be used in an interactive mode so that the user can see the effect of applying different field maps and unwarping parameters to EPI images. However, once a set of parameters has been established for a specific scanning protocol, the toolbox routines can be scripted or batched using the SPM8 user-interface. The toolbox creates a voxel-displacement map that can be used with Realign \& Unwarp for doing a combined static and dynamic distortion correction. FieldMap and Unwarp are designed only to work with images collected with the phase-encode direction aligned with the anterior-posterior direction. + for creating unwrapped field maps that can be used to do geometric distortion correction of EPI images \cite{chloe_distortion,chloe_distortion2,ja_geometric}. The methods are based on earlier work by Jezzard et al.,\cite{jezzard95} and a phase-unwrapping algorithm by Jenkinson \cite{jenkinson03}. The toolbox can be used via the SPM batch editor or in an interactive mode so that the user can see the effect of applying different field maps and unwarping parameters to EPI images. A voxel displacement map (VDM) is created that can be used with Realign \& Unwarp for doing a combined static and dynamic distortion correction or with an Apply VDM function for doing a static distortion correction on a set of realigned images. Realign \& Unwarp is designed to work only with images acquired with the phase-encode direction aligned with the anterior-posterior axis. Images acquired with phase-encode directions aligned with other axes can be distortion corrected using the FieldMap toolbox and Apply VDM utility. + +\begin{figure} +\begin{center} +\includegraphics[width=70mm]{FieldMap/fieldmap_taskmgr} +\end{center} +\caption{FieldMap using the SPM8 User Interface.\label{FM1}} +\end{figure} + +\section{Presubtracted Phase and Magnitude Data} +Calculate a voxel displacement map (VDM) from presubtracted phase and magnitude field map data (Figure \ref{FM1}). This option expects a single magnitude image and a single phase image resulting from the subtraction of two phase images (where the subtraction is usually done automatically by the scanner software). The phase image will be scaled between +/- PI. + + +\subsection{Data} +Subjects or sessions for which individual field map data has been acquired. + + +\subsubsection{Subject} +Data for this subject or field map session. + + +\paragraph{Phase Image} +Select a single phase image. This should be the result from the subtraction of two phase images (where the subtraction is usually done automatically by the scanner software). The phase image will be scaled between +/- PI. + + +\paragraph{Magnitude Image} +Select a single magnitude image. This is used for masking the phase information and coregistration with the EPI data. If two magnitude images are available, select the one acquired at the shorter echo time because it will have greater signal + + +\paragraph{FieldMap defaults} +FieldMap default values can be entered as a file or set of values. + + +\subparagraph{Defaults values} +Defaults values + + +\textbf{Echo times [short TE long TE]} +Enter the short and long echo times (in ms) of the data used to acquire the field map. + + +\textbf{Mask brain} +Select masking or no masking of the brain. If masking is selected, the magnitude image is used to generate a mask of the brain. + + +\textbf{Blip direction} +Enter the blip direction. This is the polarity of the phase-encode blips describing the direction in which k-space is traversed along the y-axis during EPI acquisition with respect to the coordinate system used in SPM. In this coordinate system, the phase encode direction corresponds with the y-direction and is defined as positive from the posterior to the anterior of the head. + +The convention used to describe the direction of the k-space traversal is based on the coordinate system used by SPM. In this coordinate system, the phase encode direction corresponds with the y-direction and is defined as positive from the posterior to the anterior of the head. The x-direction is defined as positive from left to right and the z-direction is defined as positive from foot to head. The polarity of the phase-encode blips describes in which direction k-space is traversed along the y-axis with respect to the coordinate system described here. + +\textbf{Total EPI readout time} +Enter the total EPI readout time (in ms). This is the time taken to acquire all of the phase encode steps required to cover k-space (ie one image slice). For example, if the EPI sequence has 64 phase encode steps, the total readout time is the time taken to acquire 64 echoes, e.g. total readout time = number of echos x echo spacing. This time does not include i) the duration of the excitation, ii) the delay between, the excitation and the start of the acquisition or iii) time for fat saturation etc. + + +\textbf{EPI-based field map?} +Select non-EPI or EPI based field map. The field map data may be acquired using a non-EPI sequence (typically a gradient echo sequence) or an EPI sequence. The processing will be slightly different for the two cases. If using an EPI-based field map, the resulting Voxel Displacement Map will be inverted since the field map was acquired in distorted space. + + +\textbf{Jacobian modulation?} +Select whether or not to use Jacobian modulation. This will adjust the intensities of voxels that have been stretched or compressed but in general is not recommended for EPI distortion correction + + +\textbf{uflags} +Different options for phase unwrapping and field map processing + + +\textsc{Unwrapping method} +Select method for phase unwrapping + + +\textsc{FWHM} +FWHM of Gaussian filter used to implement weighted smoothing of unwrapped maps. + + +\textsc{pad} +Size of padding kernel if required. + + +\textsc{Weighted smoothing} +Select normal or weighted smoothing. + + +\textbf{mflags} +Different options used for the segmentation and creation of the brain mask. + + +\textsc{Template image for brain masking} +Select template file for segmentation to create brain mask + + +\textsc{FWHM} +FWHM of Gaussian filter for smoothing brain mask. + + +\textsc{Number of erosions} +Number of erosions used to create brain mask. + + +\textsc{Number of dilations} +Number of dilations used to create brain mask. + + +\textsc{Threshold} +Threshold used to create brain mask from segmented data. + + +\textsc{Regularization} +Regularization value used in the segmentation. A larger value helps the segmentation to converge. + + +\subparagraph{Defaults File \label{PMDEF}} +Select the 'pm\_defaults*.m' file containing the parameters for the field map data. Please make sure that the parameters defined in the defaults file are correct for your field map and EPI sequence. To create your own customised defaults file, either edit the distributed version and/or save it with the name 'pm\_defaults\_yourname.m'. + + +\paragraph{EPI Sessions} +If a single set of field map data will be used for multiple EPI runs/sessions, select the first EPI in each run/session. A VDM file will created for each run/session, matched to the first EPI in each run/session and saved with a unique name extension. + + +\subparagraph{Session} +Data for this session. + + +\textbf{Select EPI to Unwarp} +Select a single image to distortion correct. The corrected image will be saved with the prefix u. Note that this option is mainly for quality control of correction so that the original and distortion corrected images can be displayed for comparison. To unwarp multiple images please use either Realign \& Unwarp or Apply VDM. + + +\paragraph{Match VDM to EPI?} +Match VDM file to EPI image. This will coregister the field map data to the selected EPI for each run/session. + +In general, the field map data should be acquired so that it is as closely registered with the EPI data as possible but matching can be selected if required. If a precalculated field map was loaded then the user is prompted to select a magnitude image in the same space as the field map. If real and imaginary images were selected, the toolbox automatically creates a magnitude image from these images and saves it with the name mag\_NAME-OF-FIRST-INPUT-IMAGE.img. + +\paragraph{Name extension for run/session specific VDM file} +This will be the name extension followed by an incremented integer for run/session specific VDM files. + + +\paragraph{Write unwarped EPI?} +Write out distortion corrected EPI image. The image is saved with the prefix u. Note that this option is mainly for quality control of correction so that the original and distortion corrected images can be displayed for comparison. To unwarp multiple images please use either Realign \& Unwarp or Apply VDM. + + +\paragraph{Select anatomical image for comparison} +Select an anatomical image for comparison with the distortion corrected EPI or leave empty. Note that this option is mainly for quality control of correction. + + +\paragraph{Match anatomical image to EPI?} +Match the anatomical image to the distortion corrected EPI. Note that this option is mainly for quality control of correction allowing for visual inspection and comparison of the distortion corrected EPI. + + +\section{Real and Imaginary Data} +Calculate a voxel displacement map (VDM) from real and imaginary field map data. This option expects two real and imaginary pairs of data of two different echo times. The phase images will be scaled between +/- PI. + + +\subsection{Data} +Subjects or sessions for which individual field map data has been acquired. + + +\subsubsection{Subject} +Data for this subject or field map session. + + +\paragraph{Short Echo Real Image} +Select short echo real image + + +\paragraph{Short Echo Imaginary Image} +Select short echo imaginary image + + +\paragraph{Long Echo Real Image} +Select long echo real image + + +\paragraph{Long Echo Imaginary Image} +Select long echo imaginary image + +\paragraph{Other inputs} +As for Presubtracted Phase and Magnitude Data. + +\section{Phase and Magnitude Data} +Calculate a voxel displacement map (VDM) from double phase and magnitude field map data. This option expects two phase and magnitude pairs of data of two different echo times. + + +\subsection{Data} +Subjects or sessions for which individual field map data has been acquired. + + +\subsubsection{Subject} +Data for this subject or field map session. + + +\paragraph{Short Echo Phase Image} +Select short echo phase image + + +\paragraph{Short Echo Magnitude Image} +Select short echo magnitude image + + +\paragraph{Long Echo Phase Image} +Select long echo phase image + + +\paragraph{Long Echo Magnitude Image} +Select long echo magnitude image + +\paragraph{Other inputs} +As for Presubtracted Phase and Magnitude Data. + +\section{Precalculated FieldMap (in Hz)} +Calculate a voxel displacement map (VDM) from a precalculated field map. This option expects a processed field map (ie phase unwrapped, masked if necessary and scaled to Hz). Precalculated field maps can be generated by the FieldMap toolbox and stored as fpm\_* files. + + +\subsection{Data} +Subjects or sessions for which individual field map data has been acquired. + + +\subsubsection{Subject} +Data for this subject or field map session. + + +\paragraph{Precalculated field map} +Select a precalculated field map. This should be a processed field map (ie phase unwrapped, masked if necessary and scaled to Hz) , for example as generated by the FieldMap toolbox and are stored with fpm\_* prefix. + + +\paragraph{Select magnitude image in same space as fieldmap} +Select magnitude image which is in the same space as the field map to do matching to EPI. + +\paragraph{Other inputs} +As for Presubtracted Phase and Magnitude Data. + +\section{Apply VDM } +Apply VDM (voxel displacement map) to resample voxel values in selected image(s). This allows a VDM to be applied to any images which are assumed to be already realigned (e.g. including EPI fMRI time series and DTI data). + +The VDM can be been created from a field map acquisition using the FieldMap toolbox and comprises voxel shift values which describe geometric distortions occuring as a result of magnetic susceptbility artefacts. Distortions along any single dimension can be corrected therefore input data may have been acquired with phase encode directions in X, Y (most typical) and Z. + +The selected images are assumed to be realigned to the first in the time series (e.g. using Realign: Estimate) but do not need to be resliced. The VDM is assumed to be in alignment with the images selected for resampling (note this can be achieved via the FieldMap toolbox). The resampled images are written to the input subdirectory with the same (prefixed) filename. + +e.g. The typical processing steps for fMRI time series would be 1) Realign: Estimate, 2) FieldMap to create VDM, 3) Apply VDM. + +Note that this routine is a general alternative to using the VDM in combination with Realign \& Unwarp which estimates and corrects for the combined effects of static and movement-related susceptibility induced distortions. Apply VDM can be used when dynamic distortions are not (well) modelled by Realign \& Unwarp (e.g. for fMRI data acquired with R-$>$L phase-encoding direction, high field fMRI data or DTI data). + + +\subsection{Data} +Subjects or sessions for which VDM file is being applied to images. + + +\subsubsection{Session} +Data for this session. + + +\paragraph{Images} +Select scans for this session. These are assumed to be realigned to the first in the time series (e.g. using Realign: Estimate) but do not need to be resliced + + +\paragraph{Fieldmap (vdm* file)} +Select VDM (voxel displacement map) for this session (e.g. created via FieldMap toolbox). This is assumed to be in alignment with the images selected for resampling (note this can be achieved via the FieldMap toolbox). + + +\subsection{Reslice Options} +Apply VDM reslice options + + +\subsubsection{Distortion direction} +In which direction are the distortions? Any single dimension can be corrected therefore input data may have been acquired with phase encode directions in Y (most typical), X or Z + + +\subsubsection{Reslice which images ?} +All Images (1..n) + + This applies the VDM and reslices all the images. + +All Images + Mean Image + + This applies the VDM reslices all the images and creates a mean of the resliced images. + + +\subsubsection{Interpolation} +The method by which the images are sampled when being written in a different space. Nearest Neighbour is fastest, but not recommended for image realignment. Bilinear Interpolation is probably OK for PET, but not so suitable for fMRI because higher degree interpolation generally gives better results \cite{thevenaz00a,unser93a,unser93b}. Although higher degree methods provide better interpolation, but they are slower because they use more neighbouring voxels. + + +\subsubsection{Wrapping} +This indicates which directions in the volumes the values should wrap around in. For example, in MRI scans, the images wrap around in the phase encode direction, so (e.g.) the subject's nose may poke into the back of the subject's head. These are typically: + + No wrapping - for PET or images that have already been spatially transformed. Also the recommended option if you are not really sure. + + Wrap in Y - for (un-resliced) MRI where phase encoding is in the Y direction (voxel space) etc. + + +\subsubsection{Masking} +Because of subject motion, different images are likely to have different patterns of zeros from where it was not possible to sample data. With masking enabled, the program searches through the whole time series looking for voxels which need to be sampled from outside the original images. Where this occurs, that voxel is set to zero for the whole set of images (unless the image format can represent NaN, in which case NaNs are used where possible). + + +\subsubsection{Filename Prefix} +Specify the string to be prepended to the filenames of the distortion corrected image file(s). Default prefix is 'u'. \begin{figure} \begin{center} \includegraphics[width=70mm]{FieldMap/fieldmap_gui1} \includegraphics[width=70mm]{FieldMap/fieldmap_results1} \end{center} -\caption{FieldMap GUI and Results. \label{FM1}} +\caption{FieldMap GUI and Results. \label{FM2}} \end{figure} \section{Creating Field Maps Using the FieldMap GUI} -The FieldMap Toolbox GUI is shown on the left Figure \ref{FM1}. It is divided into two parts. The top part deals with creating the field map in Hz and the bottom part deals with creating the voxel displacement map (VDM) and unwarping the EPI. The toolbox can be used by working through the different inputs in the following order: +The FieldMap Toolbox GUI is shown on the left Figure \ref{FM2}. It is divided into two parts. The top part deals with creating the field map in Hz and the bottom part deals with creating the voxel displacement map (VDM) and unwarping the EPI. The toolbox can be used by working through the different inputs in the following order: \subsection{Create field map in Hz} @@ -117,21 +409,6 @@ \subsubsection{Help} \subsubsection{Quit} Quit the toolbox and closes all windows associated with it. -\section{Using the pm\_defaults file \label{PMDEF}} -Input parameters and the mode in which the toolbox works can be customised in the defaults file called pm\_defaults.m. Different defaults files can be selected. This means that it is possible to have more than one set of default parameters, e.g. to accommodate different scanners or sequences. To be recognised by the FieldMap toolbox, these files must be named pm\_defaults\_NAME.m and have the same format as the existing pm\_defaults.m. These defaults files can be loaded using the FieldMap GUI (as described in section \ref{loaddefs}) or selected when filling in the job fields using the SPM User-Interface (as described in section 6). - -\begin{figure} -\begin{center} -\includegraphics[width=70mm]{FieldMap/fieldmap_taskmgr} -\end{center} -\caption{FieldMap using the SPM8 User Interface.\label{FM2}} -\end{figure} - -\section{Using the SPM8 User Interface \label{SPM8UI}} -FieldMap version 2.1 for SPM8 can be run using the SPM8 UI (Figure \ref{FM2}). To do this, from the top menu on the SPM8 Graphics window, select TASKS $\rightarrow$ SPM(interactive) $\rightarrow$ Tools $\rightarrow$ FieldMap. Select the type of FieldMap job to run from 1) Presubtracted Phase and Magntiude Data (this means a single phase and magnitude pair), 2) Real and Imaginary Data, 3) Phase and Magnitude Data (this means a double phase and magnitude pair) and 4) Precalculated FieldMap. In the Batch Editor, select New ``Subject'' in the lower panel, then select each item in the upper panel to fill in the different job fields. All fields marked with an X must be filled in. The other fields can be optionally filled or contain default values which can be changed if required. - -\section{Using FieldMap with multiple sessions or runs} -If multiple EPI sessions or runs have been acquired, but with only a single set of fieldmap data, it is possible to automatically create a vdm file for each session. To do this, for each new each session under the input field EPI sessions, select the first EPI in each session. A copy of the VDM file will be matched to the first EPI in each session and saved with a separate name. \section{Using the FieldMap in Batch scripts} \texttt{FieldMap\_preprocess.m} which calls \texttt{FieldMap\_create.m} gives an example of how to run the FieldMap toolbox without using the GUI. To run the script, make sure your \matlab\ path includes the directory where the FieldMap toolbox is installed. This can be done using the Set Path option under File in the \matlab\ windows manager or using the command: @@ -163,7 +440,6 @@ \section{Using the FieldMap in Batch scripts} \emph{match} match vdm file to first EPI in run (1/0). - NB: FieldMap will match the field map to the first epi image in the time series (after removing the dummy scans). Therefore, epi\_dir must be the directory that contains the epi run that all other images will be realigned to. The script will create an fpm* file, a vdm5\_* file and an unwarped version of the EPI saved with the prescript ``u''. diff --git a/man/FieldMap/fieldmap_gui1.png b/man/FieldMap/fieldmap_gui1.png index 11fa4e0..e0e3d47 100644 Binary files a/man/FieldMap/fieldmap_gui1.png and b/man/FieldMap/fieldmap_gui1.png differ diff --git a/man/FieldMap/fieldmap_results1.png b/man/FieldMap/fieldmap_results1.png index df2268e..62de716 100644 Binary files a/man/FieldMap/fieldmap_results1.png and b/man/FieldMap/fieldmap_results1.png differ diff --git a/man/FieldMap/fieldmap_taskmgr.png b/man/FieldMap/fieldmap_taskmgr.png index d6798f4..425d8c1 100644 Binary files a/man/FieldMap/fieldmap_taskmgr.png and b/man/FieldMap/fieldmap_taskmgr.png differ diff --git a/man/auditory/aud_bayes.png b/man/auditory/aud_bayes.png index b31b211..daaebb4 100644 Binary files a/man/auditory/aud_bayes.png and b/man/auditory/aud_bayes.png differ diff --git a/man/auditory/aud_bayes2.png b/man/auditory/aud_bayes2.png index dbd6da2..1ce4d8d 100644 Binary files a/man/auditory/aud_bayes2.png and b/man/auditory/aud_bayes2.png differ diff --git a/man/auditory/aud_orth.png b/man/auditory/aud_orth.png index 13bdc63..2195857 100644 Binary files a/man/auditory/aud_orth.png and b/man/auditory/aud_orth.png differ diff --git a/man/auditory/auditory.tex b/man/auditory/auditory.tex index 4741d6b..d391bd7 100644 --- a/man/auditory/auditory.tex +++ b/man/auditory/auditory.tex @@ -19,7 +19,7 @@ \section{Spatial pre-processing} \subsection{Realignment} -Under the spatial pre-processing section of the SPM base window select textsc{Realign (Est \& Res)} from the \textsc{Realign} pulldown menu. This will call up a realignment job specification in the batch editor. Then +Under the spatial pre-processing section of the SPM base window select \textsc{Realign (Est \& Res)} from the \textsc{Realign} pulldown menu. This will call up a realignment job specification in the batch editor. Then \begin{itemize} \item Highlight data, select ``New Session'', then highlight the newly created ``Session'' option. \item Select ''Specify Files'' and use the SPM file selector to choose all of your functional images eg. ``\texttt{fM000*.img}''. There should be 96 files. @@ -410,7 +410,7 @@ \subsection{Overlays} \end{center} \end{figure} -It is also possible to project and display the results on a surface mesh, we are going to use here one of the canonical mesh distributed with SPM (in MNI space). Press ``Overlays'' and choose ``Render'', then go in the \texttt{canonical} folder of your SPM installation and select file \texttt{cortex\_20484.gii} (this is a surface mesh stored using the GIfTI format) and you will obtain a figure similar to \ref{aud_render2}. +It is also possible to project and display the results on a surface mesh, we are going to use here one of the canonical mesh distributed with SPM (in MNI space). Press ``Overlays'' and choose ``Render'', then go in the \texttt{canonical} folder of your SPM installation and select file \texttt{cortex\_20484.surf.gii} (this is a surface mesh stored using the GIfTI format) and you will obtain a figure similar to \ref{aud_render2}. \begin{figure} \begin{center} diff --git a/man/auditory/bias.png b/man/auditory/bias.png index 7edee40..a69a90e 100644 Binary files a/man/auditory/bias.png and b/man/auditory/bias.png differ diff --git a/man/auditory/checkreg.png b/man/auditory/checkreg.png index 655f556..2213117 100644 Binary files a/man/auditory/checkreg.png and b/man/auditory/checkreg.png differ diff --git a/man/auditory/command.png b/man/auditory/command.png index b5078a6..bf0f4a9 100644 Binary files a/man/auditory/command.png and b/man/auditory/command.png differ diff --git a/man/auditory/con_man.png b/man/auditory/con_man.png index 04f6e85..acf62e8 100644 Binary files a/man/auditory/con_man.png and b/man/auditory/con_man.png differ diff --git a/man/auditory/con_man2.png b/man/auditory/con_man2.png index 6b637be..340a809 100644 Binary files a/man/auditory/con_man2.png and b/man/auditory/con_man2.png differ diff --git a/man/auditory/con_man3.png b/man/auditory/con_man3.png index a91ff2f..bde0f39 100644 Binary files a/man/auditory/con_man3.png and b/man/auditory/con_man3.png differ diff --git a/man/auditory/contrast.png b/man/auditory/contrast.png index 3e05e78..bce6bac 100644 Binary files a/man/auditory/contrast.png and b/man/auditory/contrast.png differ diff --git a/man/auditory/coreg.png b/man/auditory/coreg.png index b1e851c..5171ace 100644 Binary files a/man/auditory/coreg.png and b/man/auditory/coreg.png differ diff --git a/man/auditory/design.png b/man/auditory/design.png index bfd9614..85e6d36 100644 Binary files a/man/auditory/design.png and b/man/auditory/design.png differ diff --git a/man/auditory/explore.png b/man/auditory/explore.png index ed298c8..385c2b6 100644 Binary files a/man/auditory/explore.png and b/man/auditory/explore.png differ diff --git a/man/auditory/fitted.png b/man/auditory/fitted.png index 4aba37d..038bcea 100644 Binary files a/man/auditory/fitted.png and b/man/auditory/fitted.png differ diff --git a/man/auditory/gray.png b/man/auditory/gray.png index 9a2aea8..b6af345 100644 Binary files a/man/auditory/gray.png and b/man/auditory/gray.png differ diff --git a/man/auditory/interactive.png b/man/auditory/interactive.png index 6113a18..f8e6493 100644 Binary files a/man/auditory/interactive.png and b/man/auditory/interactive.png differ diff --git a/man/auditory/realign.png b/man/auditory/realign.png index 9447642..2979e9e 100644 Binary files a/man/auditory/realign.png and b/man/auditory/realign.png differ diff --git a/man/auditory/render.png b/man/auditory/render.png index f0b9b50..8eb45ba 100644 Binary files a/man/auditory/render.png and b/man/auditory/render.png differ diff --git a/man/auditory/sections.png b/man/auditory/sections.png index ebe374d..e4e783c 100644 Binary files a/man/auditory/sections.png and b/man/auditory/sections.png differ diff --git a/man/auditory/slices.png b/man/auditory/slices.png index cc5bce3..f91295f 100644 Binary files a/man/auditory/slices.png and b/man/auditory/slices.png differ diff --git a/man/auditory/smooth.png b/man/auditory/smooth.png index aa6e659..6b21129 100644 Binary files a/man/auditory/smooth.png and b/man/auditory/smooth.png differ diff --git a/man/auditory/spm1.png b/man/auditory/spm1.png index fa2c4bc..288441c 100644 Binary files a/man/auditory/spm1.png and b/man/auditory/spm1.png differ diff --git a/man/auditory/volume.png b/man/auditory/volume.png index 2538b1b..a20d989 100644 Binary files a/man/auditory/volume.png and b/man/auditory/volume.png differ diff --git a/man/batch/batch.tex b/man/batch/batch.tex index 1744e3a..c4cfa49 100644 --- a/man/batch/batch.tex +++ b/man/batch/batch.tex @@ -1,11 +1,12 @@ -\chapter{Batch interface} -\label{Chap:batch_interface} +\chapter{Batch tutorial} +\label{Chap:batch:tutorial} Details about the algorithms used for data processing are given in the other sections of this manual. This section explains how a sequence of processing steps can be run at once without MATLAB programming. SPM8 includes -\texttt{matlabbatch}\footnote{\url{http://sourceforge.net/projects/matlabbatch}} which has been derived from the SPM5 -batch system, but is also available as a separate package. +\texttt{matlabbatch}\footnote{\url{http://sourceforge.net/projects/matlabbatch}} +which has been derived from the SPM5 batch system, but is also available as a +separate package. In \texttt{matlabbatch}, each data processing step is called ``module''. There are e.g.\ modules for spatial processing of MRI data (realignment, @@ -31,7 +32,7 @@ \chapter{Batch interface} \item[Multiple batches] Multiple batches can be loaded and executed together. \end{description} -\section{Batch tutorial - single subject} +\section{Single subject} In this tutorial we will develop a batch for spatial processing and fMRI statistics of a single subject of the ``Face'' example dataset (see @@ -92,18 +93,10 @@ \subsubsection{SPM processing} \subsection{Add modules to the batch} -\begin{figure}[htbp] - \centering - \includegraphics{batch/tasks} - \caption{TASKS menu in ``Graphics'' window} - \label{fig:tasks} -\end{figure} The helper modules and the SPM processing modules can be assembled using the -GUI. Click the ``BATCH'' button in the SPM Menu window or locate the Graphics -window and open the batch editor by selecting ``BATCH'' from the ``TASKS'' -menu (fig.~\ref{fig:tasks}). First, add the helper modules, followed by the -SPM modules in the order listed above. Do not configure any details until you -have selected all modules. +GUI. Click the ``BATCH'' button in the SPM Menu window. First, add the helper +modules, followed by the SPM modules in the order listed above. Do not configure +any details until you have selected all modules. \begin{figure} \centering @@ -532,12 +525,8 @@ \subsubsection{Complete and run a pre-specified job} % fMRI model specification: Multiple conditions - cfg_files inputs{4, crun} = MATLAB_CODE_TO_FILL_INPUT; end -job_id = cfg_util('initjob', jobs); -sts = cfg_util('filljob', job_id, inputs{:}); -if sts - cfg_util('run', job_id); -end -cfg_util('deljob', job_id); +spm('defaults','fmri'); +spm_jobman('serial',jobs,'',inputs{:}); \end{verbatim} The skeleton needs to be adapted to the actual data layout by adding @@ -556,193 +545,3 @@ \subsection{Modifying a saved job} \verb|.m| files. These files contain a number of MATLAB commands, which will create a variable \verb|matlabbatch|. The commands can be modified to set different values, add or remove options. - -\section{SPM5 to matlabbatch transition guide} -\label{sec:overview} - -This is a short overview to describe code organisation and interfaces between -SPM and the batch system. - -\subsection{Code Reorganisation} -\label{sec:overcode} - -The following paths have changed: -\begin{itemize} -\item \verb|fullfile(spm('dir'),'matlabbatch')| Core batch system. -\item \verb|fullfile(spm('dir'),'config')| New SPM config files. -\item \verb|fullfile(spm('dir'),'oldconfig')| Old SPM config files (unused) -\item \verb|spm_jobman.m| and \verb|spm_select.m| replaced with compatibility - code -\item \verb|spm_Menu.fig| Callbacks adapted -\end{itemize} - -Configuration code has been generated automatically from the existing SPM -configuration using \verb|cfg_struct2cfg| and \verb|gencode|. This sometimes -results in redundant/duplicate code. Also, conditional constructs like -\verb|if|, \verb|case| may not have been considered. - -Some assignments to configuration items are guarded by validity -checks. Usually, there will be a warning issued if a wrong value is -supplied. Special care needs to be taken for \verb|.prog|, \verb|.vfiles|, -\verb|.vout|, \verb|.check| functions or function handles. The functions -referenced here must be on MATLAB path before they are assigned to one of -these fields. For toolboxes, this implies that toolbox paths must be added at -the top of the configuration file. - -For details, see section~\ref{sec:code}. - -\subsection{Interfaces between SPM and Matlabbatch} -\label{sec:overinter} - -\begin{description} -\item[Unchanged] harvested job structure. -\item[Changed] Top-level node in SPM config now called \verb|spmjobs| instead - of \verb|jobs|. New overall top-level node - \verb|matlabbatch|. \verb|spm_jobman| will convert and load SPM5 style batch - jobs into the new batch system. -\item[Changed] Configuration file syntax - instead of structs, configuration - items are now objects. Structs of type \verb|| are now represented as - objects of class \verb|cfg_|. Existing SPM5 configuration can - be imported using \verb|cfg_struct2cfg|. There is a new class - \verb|cfg_exbranch| which is used for branches that have a \verb|.prog| - field. -\item[Deprecated] Virtual files have been replaced by dependencies. These - require computations to return a single output argument (e.g. a cell, - struct). Parts of this output argument can be passed on to new inputs at - run-time. Virtual files are treated as a special output argument. -\item[Added] Interface to the batch system - \begin{itemize} - \item \verb|cfg_util| Configuration management, job management, job - execution - \item \verb|cfg_serial| A utility to fill missing inputs and run a job - (optionally with a GUI input function) - \item \verb|cfg_ui| GUI - inspired by \verb|spm_jobman|, but modified to - work around some MATLAB GUI ``features'' (like input widgets loosing focus - before editing has finished). - \end{itemize} - -\end{description} - -\section{Configuration Code Details} -\label{sec:code} - -Configuration code has been split into two files per configuration: -\begin{description} -\item[spm\_cfg\_*.m] Configuration classes, \verb|.check|, \verb|.vout| - subfunctions -\item[spm\_run\_*.m] Run-time code, takes job structure as input and returns - output structure as specified in \verb|.vout|. -\end{description} -In a few cases (where there was no additional magic in the code), run-time -code has been integrated into the main SPM code. This may be useful to run -test batches without using the configuration/batch system. - -\subsection{Virtual Outputs} - -Virtual outputs are described by arrays of \verb|cfg_dep| objects. These -objects contain a ``source'' and a ``target'' part. Functions may have more -than one virtual output (e.g. one output per session, a collection of results -variables). One \verb|cfg_dep| object has to be created for each output. - -Only two fields in the ``source'' part need to be set in a \verb|.vout| -callback: -\begin{description} -\item[sname] A display name for this output. This will appear in the - dependencies list and should describe the contents of this dependency. -\item[src\_output] A subscript reference that can be used to address this - output in the variable returned at run-time. -\item[tgt\_spec (optional)] A description on what kind of inputs this output - should be displayed as dependency. This is not very convenient yet, the - \verb|match| and \verb|cfg_findspec| methods are very restrictive in the - kind of expressions that are allowed. -\end{description} - -The \verb|.vout| callback will be evaluated once the configuration system -thinks that enough information about the \emph{structure} of the outputs is -available. This condition is met, once all in-tree nodes -\verb|cfg_(ex)branch|, \verb|cfg_choice|, \verb|cfg_repeat| have the required -number of child nodes. - -The \verb|.vout| callback is called with a job structure as input, but its -code \emph{should not rely} on the evaluation of any contents of this -structure (or at least provide a fallback). The contents of the leaf nodes may -not be set or may contain a dependency object instead of a value during -evalution of \verb|.vout|. - -The ``target'' part will be filled by the configuration classes, the -\verb|src_exbranch| field is set in \verb|cfg_util|. - -\subsection{SPM Startup} - -The top level configuration file for SPM is \verb|spm_cfg.m|. It collects SPM -core configuration files and does toolbox autodetection. If a toolbox -directory contains \verb|*_cfg_*.m| files, they will be loaded. Otherwise, if -there are only SPM5-style \verb|*_config_*.m| files, the configuration will be -converted at run-time using \verb|cfg_struct2cfg|. - -\subsection{Defaults Settings} - -In Matlabbatch, there are different ways to set defaults: -\begin{enumerate} -\item \label{def:cf}in the configuration file itself, -\item \label{def:cd}in a defaults file, which has a structure similar to a harvested - job, -\item \label{def:def}using a \verb|.def| field for leaf items. -\end{enumerate} -Defaults set using option \ref{def:cf} or \ref{def:cd} will only be -updated at SPM/matlabbatch startup. Defaults set using option -\ref{def:def} will be set once a new job is started. These defaults take -precedence over the other defaults. - -In core SPM, these defaults refer to \verb|spm_get_defaults|, which accesses -\verb|spm_defaults|. Toolboxes may use their own callback functions. - -\subsection{Toolbox Migration} - -In the \verb|fullfile(spm('dir'),'toolbox')| folder there exists a migration -utility \verb|spm_tbx_config2cfg.m|. This utility will create a -\verb|*_cfg_*.m| and a \verb|*_def_*.m| file based on the configuration tree -given as input argument. - -Toolboxes should set their defaults using the \verb|.def| fields, -using a mechanism similar to \verb|spm_get_defaults|. This allows for -flexibility without interfering with SPMs own defaults. - -\section{Utilities} - -\subsection{Batch Utilities} - -Matlabbatch is designed to support multiple applications. A standard -application ``BasicIO'' is enabled by default. Among other options, it -contains file/file selection manipulation utilities which can be used as as -dependency source if multiple functions require the same set of files as input -argument. For debugging purposes, ``Pass Output to Workspace'' can be used to -assign outputs of a computation to a workspace variable. - -The \verb|cfg_confgui| folder contains an application which describes all -configuration items in terms of configuration items. It is not enabled by -default, but can be added to the batch system using -\verb|cfg_util('addapp'...)|. This utility can be used generate a batch -configuration file with the batch system itself. - -\subsection{Matlab Code Generation} - -The \verb|gencode| utility generates MATLAB \verb|.m| file code for any kind -of MATLAB variable. This is used to save batch files as well as to generate -configuration code. - -\subsection{Configuration Management} - -The backend utility to manage the configuration data is \verb|cfg_util|. It -provides callbacks to add application configurations, and to load, modify, -save or run jobs. These callbacks are used by two frontends: \verb|cfg_ui| is -a MATLAB GUI, while \verb|cfg_serial| can be used both as a GUI and in script -mode. In script mode, it will fill in job inputs from an argument list. This -allows to run predefined jobs with e.g. subject dependent inputs without -knowing the exact details of the job structure. - - -%%% Local Variables: -%%% mode: latex -%%% TeX-master: ../manual.tex -%%% End: diff --git a/man/batch/batch_basicio.png b/man/batch/batch_basicio.png index ba53d68..5b92361 100644 Binary files a/man/batch/batch_basicio.png and b/man/batch/batch_basicio.png differ diff --git a/man/batch/batch_dependencies.png b/man/batch/batch_dependencies.png index 11eb0af..29f84d0 100644 Binary files a/man/batch/batch_dependencies.png and b/man/batch/batch_dependencies.png differ diff --git a/man/batch/batch_multi_subject_template.png b/man/batch/batch_multi_subject_template.png index 4313191..f6c1c6f 100644 Binary files a/man/batch/batch_multi_subject_template.png and b/man/batch/batch_multi_subject_template.png differ diff --git a/man/batch/batch_single_subject.png b/man/batch/batch_single_subject.png index 8b47cbe..52b7e2c 100644 Binary files a/man/batch/batch_single_subject.png and b/man/batch/batch_single_subject.png differ diff --git a/man/batch/batch_single_subject_template.png b/man/batch/batch_single_subject_template.png index f720a6d..0c1ed8f 100644 Binary files a/man/batch/batch_single_subject_template.png and b/man/batch/batch_single_subject_template.png differ diff --git a/man/batch/batch_single_subject_template_nodeps.png b/man/batch/batch_single_subject_template_nodeps.png index 87a2f4e..487c2af 100644 Binary files a/man/batch/batch_single_subject_template_nodeps.png and b/man/batch/batch_single_subject_template_nodeps.png differ diff --git a/man/batch/batch_spm.png b/man/batch/batch_spm.png index 778391a..46d24dd 100644 Binary files a/man/batch/batch_spm.png and b/man/batch/batch_spm.png differ diff --git a/man/batch/devel.tex b/man/batch/devel.tex new file mode 100644 index 0000000..350f631 --- /dev/null +++ b/man/batch/devel.tex @@ -0,0 +1,180 @@ +\chapter{Developer's guide} +\label{Chap:batch:devel} + +\section{SPM5 to Matlabbatch transition guide} + +This is a short overview to describe code organisation and interfaces between +SPM and the batch system. + +\subsection{Code Reorganisation} + +The following paths have changed: +\begin{itemize} +\item \verb|fullfile(spm('dir'),'matlabbatch')| Core batch system. +\item \verb|fullfile(spm('dir'),'config')| New SPM config files. +\item \verb|fullfile(spm('dir'),'oldconfig')| Old SPM config files (unused) +\item \verb|spm_jobman.m| and \verb|spm_select.m| replaced with compatibility + code +\item \verb|spm_Menu.fig| Callbacks adapted +\end{itemize} + +Configuration code has been generated automatically from the existing SPM +configuration using \verb|cfg_struct2cfg| and \verb|gencode|. This sometimes +results in redundant/duplicate code. Also, conditional constructs like +\verb|if|, \verb|case| may not have been considered. + +Some assignments to configuration items are guarded by validity +checks. Usually, there will be a warning issued if a wrong value is +supplied. Special care needs to be taken for \verb|.prog|, \verb|.vfiles|, +\verb|.vout|, \verb|.check| functions or function handles. The functions +referenced here must be on MATLAB path before they are assigned to one of +these fields. For toolboxes, this implies that toolbox paths must be added at +the top of the configuration file. + +\subsection{Interfaces between SPM and Matlabbatch} + +\begin{description} +\item[Unchanged] harvested job structure. +\item[Changed] Top-level node in SPM config now called \verb|spmjobs| instead + of \verb|jobs|. New overall top-level node + \verb|matlabbatch|. \verb|spm_jobman| will convert and load SPM5 style batch + jobs into the new batch system. +\item[Changed] Configuration file syntax - instead of structs, configuration + items are now objects. Structs of type \verb|| are now represented as + objects of class \verb|cfg_|. Existing SPM5 configuration can + be imported using \verb|cfg_struct2cfg|. There is a new class + \verb|cfg_exbranch| which is used for branches that have a \verb|.prog| + field. +\item[Deprecated] Virtual files have been replaced by dependencies. These + require computations to return a single output argument (e.g. a cell, + struct). Parts of this output argument can be passed on to new inputs at + run-time. Virtual files are treated as a special output argument. +\item[Added] Interface to the batch system + \begin{itemize} + \item \verb|cfg_util| Configuration management, job management, job + execution + \item \verb|cfg_serial| A utility to fill missing inputs and run a job + (optionally with a GUI input function) + \item \verb|cfg_ui| GUI - inspired by \verb|spm_jobman|, but modified to + work around some MATLAB GUI ``features'' (like input widgets loosing focus + before editing has finished). + \end{itemize} + +\end{description} + +\section{Configuration Code Details} + +Configuration code has been split into two files per configuration: +\begin{description} +\item[spm\_cfg\_*.m] Configuration classes, \verb|.check|, \verb|.vout| + subfunctions +\item[spm\_run\_*.m] Run-time code, takes job structure as input and returns + output structure as specified in \verb|.vout|. +\end{description} +In a few cases (where there was no additional magic in the code), run-time +code has been integrated into the main SPM code. This may be useful to run +test batches without using the configuration/batch system. + +\subsection{Virtual Outputs} + +Virtual outputs are described by arrays of \verb|cfg_dep| objects. These +objects contain a ``source'' and a ``target'' part. Functions may have more +than one virtual output (e.g. one output per session, a collection of results +variables). One \verb|cfg_dep| object has to be created for each output. + +Only two fields in the ``source'' part need to be set in a \verb|.vout| +callback: +\begin{description} +\item[sname] A display name for this output. This will appear in the + dependencies list and should describe the contents of this dependency. +\item[src\_output] A subscript reference that can be used to address this + output in the variable returned at run-time. +\item[tgt\_spec (optional)] A description on what kind of inputs this output + should be displayed as dependency. This is not very convenient yet, the + \verb|match| and \verb|cfg_findspec| methods are very restrictive in the + kind of expressions that are allowed. +\end{description} + +The \verb|.vout| callback will be evaluated once the configuration system +thinks that enough information about the \emph{structure} of the outputs is +available. This condition is met, once all in-tree nodes +\verb|cfg_(ex)branch|, \verb|cfg_choice|, \verb|cfg_repeat| have the required +number of child nodes. + +The \verb|.vout| callback is called with a job structure as input, but its +code \emph{should not rely} on the evaluation of any contents of this +structure (or at least provide a fallback). The contents of the leaf nodes may +not be set or may contain a dependency object instead of a value during +evalution of \verb|.vout|. + +The ``target'' part will be filled by the configuration classes, the +\verb|src_exbranch| field is set in \verb|cfg_util|. + +\subsection{SPM Startup} + +The top level configuration file for SPM is \verb|spm_cfg.m|. It collects SPM +core configuration files and does toolbox autodetection. If a toolbox +directory contains \verb|*_cfg_*.m| files, they will be loaded. Otherwise, if +there are only SPM5-style \verb|*_config_*.m| files, the configuration will be +converted at run-time using \verb|cfg_struct2cfg|. + +\subsection{Defaults Settings} + +In Matlabbatch, there are different ways to set defaults: +\begin{enumerate} +\item \label{def:cf}in the configuration file itself, +\item \label{def:cd}in a defaults file, which has a structure similar to a harvested + job, +\item \label{def:def}using a \verb|.def| field for leaf items. +\end{enumerate} +Defaults set using option \ref{def:cf} or \ref{def:cd} will only be +updated at SPM/matlabbatch startup. Defaults set using option +\ref{def:def} will be set once a new job is started. These defaults take +precedence over the other defaults. + +In core SPM, these defaults refer to \verb|spm_get_defaults|, which accesses +\verb|spm_defaults|. Toolboxes may use their own callback functions. + +\subsection{Toolbox Migration} + +In the \verb|fullfile(spm('dir'),'toolbox')| folder there exists a migration +utility \verb|spm_tbx_config2cfg.m|. This utility will create a +\verb|*_cfg_*.m| and a \verb|*_def_*.m| file based on the configuration tree +given as input argument. + +Toolboxes should set their defaults using the \verb|.def| fields, +using a mechanism similar to \verb|spm_get_defaults|. This allows for +flexibility without interfering with SPMs own defaults. + +\section{Utilities} + +\subsection{Batch Utilities} + +Matlabbatch is designed to support multiple applications. A standard +application ``BasicIO'' is enabled by default. Among other options, it +contains file/file selection manipulation utilities which can be used as as +dependency source if multiple functions require the same set of files as input +argument. For debugging purposes, ``Pass Output to Workspace'' can be used to +assign outputs of a computation to a workspace variable. + +The \verb|cfg_confgui| folder contains an application which describes all +configuration items in terms of configuration items. It is not enabled by +default, but can be added to the batch system using +\verb|cfg_util('addapp'...)|. This utility can be used generate a batch +configuration file with the batch system itself. + +\subsection{MATLAB Code Generation} + +The \verb|gencode| utility generates MATLAB \verb|.m| file code for any kind +of MATLAB variable. This is used to save batch files as well as to generate +configuration code. + +\subsection{Configuration Management} + +The backend utility to manage the configuration data is \verb|cfg_util|. It +provides callbacks to add application configurations, and to load, modify, +save or run jobs. These callbacks are used by two frontends: \verb|cfg_ui| is +a MATLAB GUI, while \verb|cfg_serial| can be used both as a GUI and in script +mode. In script mode, it will fill in job inputs from an argument list. This +allows to run predefined jobs with e.g. subject dependent inputs without +knowing the exact details of the job structure. diff --git a/man/batch/face_single_subject_script.m b/man/batch/face_single_subject_script.m index 954aad1..a1cc968 100644 --- a/man/batch/face_single_subject_script.m +++ b/man/batch/face_single_subject_script.m @@ -13,9 +13,5 @@ inputs{3, crun} = MATLAB_CODE_TO_FILL_INPUT; % Coreg: Estimate: Source Image - cfg_files inputs{4, crun} = MATLAB_CODE_TO_FILL_INPUT; % fMRI model specification: Multiple conditions - cfg_files end -job_id = cfg_util('initjob', jobs); -sts = cfg_util('filljob', job_id, inputs{:}); -if sts - cfg_util('run', job_id); -end -cfg_util('deljob', job_id); +spm('defaults','fmri'); +spm_jobman('serial',jobs,'',inputs{:}); diff --git a/man/batch/flow.png b/man/batch/flow.png index 3861137..3c51e83 100644 Binary files a/man/batch/flow.png and b/man/batch/flow.png differ diff --git a/man/batch/multimodal_fmri_script.m b/man/batch/multimodal_fmri_script.m index ea14d58..d0facae 100644 --- a/man/batch/multimodal_fmri_script.m +++ b/man/batch/multimodal_fmri_script.m @@ -24,13 +24,13 @@ inputs = cell(6,numel(subjdirs)); for sub = 1:numel(subjdirs) inputs{1,sub} = {fullfile(studydir,subjdirs{sub})}; - inputs{2,sub} = cfg_getfile('FPList',fullfile(inputs{1,sub}{1}, ... - 'fMRI','Session1'),'^f.*\.img'); - inputs{3,sub} = cfg_getfile('FPList',fullfile(inputs{1,sub}{1}, ... - 'fMRI','Session2'),'^f.*\.img'); + inputs{2,sub} = cellstr(spm_select('FPList',fullfile(inputs{1,sub}{1}, ... + 'fMRI','Session1'),'^f.*\.img')); + inputs{3,sub} = cellstr(spm_select('FPList',fullfile(inputs{1,sub}{1}, ... + 'fMRI','Session2'),'^f.*\.img')); inputs{4,sub} = {fullfile(inputs{1,sub}{1},'sMRI','smri.img')}; inputs{5,sub} = {fullfile(inputs{1,sub}{1},'fMRI','trials_ses1.mat')}; inputs{6,sub} = {fullfile(inputs{1,sub}{1},'fMRI','trials_ses2.mat')}; end spm('defaults','fmri'); -spm_jobman('serial',jobs,'',inputs{:}); \ No newline at end of file +spm_jobman('serial',jobs,'',inputs{:}); diff --git a/man/biblio/methods_group.bib b/man/biblio/methods_group.bib index 42de7e4..ea16f61 100644 --- a/man/biblio/methods_group.bib +++ b/man/biblio/methods_group.bib @@ -2510,30 +2510,6 @@ @Article{cc_induced keyword = {DCM} } -@Article{karl_filtering, - author = karl, - title = {Variational filtering}, - journal = ni, - year = 2008, - volume = 41, - number = {3}, - pages = {747--766}, - doi = {10.1016/j.neuroimage.2008.03.017}, - keyword = {Bayesian} -} - -@Article{karl_DEM, - author = karl # and # nelson # and # jean, - title = {{DEM}: A variational treatment of dynamic systems}, - journal = ni, - year = 2008, - volume = 41, - number = {3}, - pages = {849--885}, - doi = {10.1016/j.neuroimage.2008.02.054}, - keyword = {DEM} -} - @Article{rm_spectralnmm, author = rm # and # sjk # and # {N. Rombach} # and # {W.T. O'Connor} # and # {K.J. Murphy} # and # {R.B. Reilly} # and # karl, title = {Bayesian estimation of synaptic physiology from the spectral responses of neural masses}, @@ -3094,10 +3070,11 @@ @Article{rnah_fmripriors title = {A Parametric Empirical Bayesian framework for f{MRI}-constrained {MEG}/{EEG} source reconstruction}, journal = hbm, year = {2010}, -volume = {in press}, -number = {}, -pages = {}, -doi = {} +volume = {31}, +number = {10}, +pages = {1512--1531}, +doi = {10.1002/hbm.20956}, +pdf = {/spm/doc/papers/rnah_HBM_10_fMRIPriors_EMEG.pdf} } @Article{vl_optibf, @@ -3227,6 +3204,147 @@ @Article{klaas_effcon_fmri keyword = {DCM, fMRI} } +@Article{karl_network_discovery, +author = karl # and # {B. Li} # and # jean # and # klaas, +title = {Network discovery with DCM}, +journal = ni, +year = {2010}, +volume = {in press}, +number = {}, +pages = {}, +doi = {10.1016/j.neuroimage.2010.12.039}, +keyword = {DCM} +} + +@Article{meeg_spm8, +author = vl # and # jm # and # sjk # and # cp # and # rnah # and # jk # and # gb # and # {R. Oostenveld} # and # jean # and # gf #and # will # and # karl, +title = {EEG and MEG data analysis in SPM8}, +journal = {Comput. Intell. Neurosci.}, +year = {2010}, +volume = {in press}, +number = {}, +pages = {}, +doi = {}, +keyword = {introduction, EEG, MEG} +} + +@Article{jean_oto1, +author = jean # and # {H.E.M den Ouden} # and # {M. Pessiglione} # and # klaas # and # sjk # and # karl, +title = {Observing the observer (I): meta-Bayesian models of learning and decision-making}, +journal = {Plos One}, +year = {2010}, +volume = {5}, +number = {12}, +pages = {e15554}, +doi = {10.1371/journal.pone.0015554}, +pdf = {/spm/doc/papers/Daunizeau_PLOSOne_5_e15554.pdf}, +keyword = {Bayesian} +} + +@Article{jean_oto2, +author = jean # and # {H.E.M den Ouden} # and # {M. Pessiglione} # and # sjk # and # karl # and # klaas, +title = {Observing the observer (II): deciding when to decide}, +journal = {Plos One}, +year = {2010}, +volume = {5}, +number = {12}, +pages = {e15555}, +doi = {10.1371/journal.pone.0015555}, +pdf = {/spm/doc/papers/Daunizeau_PLOSOne_5_e15555.pdf}, +keyword = {Bayesian} +} + +@Article{maria_eeg_fmri_integ, +author = mjr # and # jean # and # karl, +title = {EEG-fMRI integration : a critical review of biophysical modelling and data analysis approaches}, +journal = {J. Integrative Neurosci.}, +year = {2010}, +volume = {9}, +number = {4}, +pages = {453--476}, +doi = {}, +keyword = {} +} + +@Article{james_topological_inference, +author = jk # and # karl, +title = {Topological Inference for {EEG} and {MEG}}, +journal = {The Annals of Applied Statistics}, +year = {2010}, +volume = {4}, +number = {3}, +pages = {1272--1290}, +doi = {10.1214/10-AOAS337}, +pdf = {/spm/doc/papers/1011.2901v1.pdf}, +keyword = {RFT, topological, EEG, MEG} +} + + +@Article{karl_action_behaviour, +author = karl # and # jean # and # jk # and # sjk, +title = {Action and behavior: a free-energy formulation}, +journal = {Biol. Cybern.}, +year = {2010}, +volume = {102}, +number = {3}, +pages = {227--260}, +doi = {10.1007/s00422-010-0364-z}, +pdf = {/spm/doc/papers/Action_and_behavior_A_free-energy_formulation.pdf}, +keyword = {DEM} +} + +@Article{harriet_attention_uncertainty, +author = {Harriet Feldman} # and # karl, +title = {Attention, uncertainty, and free-energy}, +journal = {Frontiers in Human Neuroscience}, +year = {2010}, +volume = {4}, +number = {215}, +pages = {}, +doi = {10.3389/fnhum.2010.00215}, +pdf = {/spm/doc/papers/Attention_uncertainty_and_free-energy.pdf}, +keyword = {DEM} +} + +@Article{karl_cortical_circuits, +author = karl # and # sjk, +title = {Cortical circuits for perceptual inference}, +journal = {Neural Networks}, +year = {2009}, +volume = {22}, +number = {}, +pages = {1093--1104}, +doi = {10.1016/j.neunet.2009.07.023}, +pdf = {/spm/doc/papers/Cortical_circuits_for_perceptual_inference.pdf}, +keyword = {DEM} +} + +@Article{karl_variational_filtering, + author = karl, + title = {Variational filtering}, + journal = ni, + year = 2008, + volume = 41, + number = {3}, + pages = {747--766}, + doi = {10.1016/j.neuroimage.2008.03.017}, + pdf = {/spm/doc/papers/Variational_filtering.pdf}, + keyword = {DEM} +} + +@Article{karl_DEM, + author = karl # and # nelson # and # jean, + title = {{DEM}: A variational treatment of dynamic systems}, + journal = ni, + year = 2008, + volume = 41, + number = {3}, + pages = {849--885}, + doi = {10.1016/j.neuroimage.2008.02.054}, + pdf = {/spm/doc/papers/DEM_A_variational_treatment_of_dynamic_systems.pdf}, + keyword = {DEM} +} + @Article{karl_generalised_filtering, author = karl # and # klaas # and # bl # and # jean, title = {Generalised Filtering}, @@ -3237,5 +3355,32 @@ @Article{karl_generalised_filtering pages = {}, doi = {10.1155/2010/621670}, pdf = {/spm/doc/papers/Friston_MathProblEngin_2010_621670.pdf}, -keyword = {} +keyword = {DEM} +} + + +@Article{karl_hierarchical_models, +author = karl, +title = {Hierarchical Models in the Brain}, +journal = {PLOS Computational Biology}, +year = {2008}, +volume = {4}, +number = {11}, +pages = {e1000211}, +doi = {10.1371/journal.pcbi.1000211}, +pdf = {/spm/doc/papers/Hierarchical_Models_in_the_Brain.pdf}, +keyword = {DEM} +} + +@Article{karl_reinforcement_learning, +author = karl # and # jean # and # sjk, +title = {Reinforcement Learning or Active Inference?}, +journal = {PLOS One}, +year = {2009}, +volume = {4}, +number = {7}, +pages = {e6421}, +doi = {10.1371/journal.pone.0006421}, +pdf = {/spm/doc/papers/Reinforcement_Learning_or_Active_Inference.pdf}, +keyword = {DEM} } diff --git a/man/dcm/Fig9.png b/man/dcm/Fig9.png index 79bbfde..1f5114b 100644 Binary files a/man/dcm/Fig9.png and b/man/dcm/Fig9.png differ diff --git a/man/dcm/dcm.tex b/man/dcm/dcm.tex index bc7e354..09dc14e 100644 --- a/man/dcm/dcm.tex +++ b/man/dcm/dcm.tex @@ -288,8 +288,13 @@ \subsection{Comparing models} \begin{enumerate} \item Press the ``DCM'' button. \item Choose \textsc{Compare}. - \item Number of models to compare: 2 - \item Select the two models, e.g. in the order \texttt{DCM\_mod\_bwd.mat} and \texttt{DCM\_mod\_fwd.mat}. + \item In the Batch Editor window that opened, fill in the ``BMS: DCM'' module: + \begin{enumerate} + \item \texttt{Directory}: choose current directory, + \item \texttt{Data}: add a New Subject with a New Session and select the two models, e.g. in the order \texttt{DCM\_mod\_bwd.mat} and \texttt{DCM\_mod\_fwd.mat}, + \item \texttt{Inference method}: choose ``Fixed effects (FFX)''. + \end{enumerate} + \item Press Run (the green triangle in the Batch Editor). \end{enumerate} The Graphics window, Fig.~\ref{dcm_fig9}, now shows a bar plot of the model evidence. You can see that our second model is better than the first one. diff --git a/man/dcm_ssr/fig1.png b/man/dcm_ssr/fig1.png index 36116ff..aa92e34 100644 Binary files a/man/dcm_ssr/fig1.png and b/man/dcm_ssr/fig1.png differ diff --git a/man/dcm_ssr/fig2.png b/man/dcm_ssr/fig2.png index cef3d19..a511e6f 100644 Binary files a/man/dcm_ssr/fig2.png and b/man/dcm_ssr/fig2.png differ diff --git a/man/dcm_ssr/fig3.png b/man/dcm_ssr/fig3.png index 42976ad..d104b83 100644 Binary files a/man/dcm_ssr/fig3.png and b/man/dcm_ssr/fig3.png differ diff --git a/man/example_scripts/simmegdip_for_faces.m b/man/example_scripts/simmegdip_for_faces.m index 2eb6bfe..825d334 100644 --- a/man/example_scripts/simmegdip_for_faces.m +++ b/man/example_scripts/simmegdip_for_faces.m @@ -37,8 +37,8 @@ allmeshvert_mni=D.inv{1}.mesh.tess_mni.vert; allmeshvert_ctf=D.inv{1}.forward.mesh.vert; allmeshfaces=D.inv{1}.forward.mesh.face; -allmeshnorms_ctf=spm_eeg_inv_normals(allmeshvert_ctf,allmeshfaces); -allmeshnorms_mni=spm_eeg_inv_normals(allmeshvert_mni,allmeshfaces); +allmeshnorms_ctf=spm_mesh_normals(struct('faces',allmeshfaces,'vertices',allmeshvert_ctf),true); +allmeshnorms_mni=spm_mesh_normals(struct('faces',allmeshfaces,'vertices',allmeshvert_mni),true); %%% FORCE A SINGE SPHERE HEAD MODEL- simpler to compare inversions headmodels = {'Single Sphere', 'MEG Local Spheres', 'Single Shell'}; diff --git a/man/example_scripts/simmegdip_mult_subj.m b/man/example_scripts/simmegdip_mult_subj.m index 18fdf76..90feb65 100644 --- a/man/example_scripts/simmegdip_mult_subj.m +++ b/man/example_scripts/simmegdip_mult_subj.m @@ -2,17 +2,17 @@ %% template, %% can vary source std in amplitude and/or location across subjects -cd C:\users\gbarnes\documents\mv_multsubj +cd('D:\SPM MEEG 2010\Preprocessing demo\MEG'); Nsubj=10; %% ORIGINAL FACES DATA FILE origspmfilename='cdbespm8_SPM_CTF_MEG_example_faces1_3D.mat' -outpath='C:\users\gbarnes\documents\simdata_vlad'; +outpath='D:\Data\Scaling\simulated'; %% FOR SIMULATED NOISE- recording BW of 80Hz, white noise level 10ft/rtHz -noiselevel=10*1e-15; +noiselevel=50*1e-15; BW=80; -cross_subj_disp=0; %% sd of positions across subjects mm -cross_subj_sdamp_pc=0; %% %sd of amplitude variation across subjects +cross_subj_disp=5; %% sd of positions across subjects mm +cross_subj_sdamp_pc=100; %% %sd of amplitude variation across subjects %% set frequency and amplitude of the two dipoles defined above %% for each condition (faces/scrambled) separately @@ -35,7 +35,7 @@ for s=1:Nsubj, - dipamp_subj=dipamp+dipamp.*randn(size(dipamp))*cross_subj_sdamp_pc./100;; + dipamp_subj=dipamp+dipamp.*randn(size(dipamp))*cross_subj_sdamp_pc./100; %% OUTPUT SIMULATED DATA FILE spmfilename=[outpath filesep sprintf('%s%d',substr,s)]; @@ -60,8 +60,8 @@ allmeshvert_mni=D.inv{1}.mesh.tess_mni.vert; allmeshvert_ctf=D.inv{1}.forward.mesh.vert; allmeshfaces=D.inv{1}.forward.mesh.face; -allmeshnorms_ctf=spm_eeg_inv_normals(allmeshvert_ctf,allmeshfaces); -allmeshnorms_mni=spm_eeg_inv_normals(allmeshvert_mni,allmeshfaces); +allmeshnorms_ctf=spm_mesh_normals(struct('faces',allmeshfaces,'vertices',allmeshvert_ctf),true); +allmeshnorms_mni=spm_mesh_normals(struct('faces',allmeshfaces,'vertices',allmeshvert_mni),true); %%% FORCE A SINGE SPHERE HEAD MODEL- simpler to compare inversions headmodels = {'Single Sphere', 'MEG Local Spheres', 'Single Shell'}; diff --git a/man/faces/cat3_contrast.png b/man/faces/cat3_contrast.png index dfeaa62..d419010 100644 Binary files a/man/faces/cat3_contrast.png and b/man/faces/cat3_contrast.png differ diff --git a/man/faces/cat3_psth.png b/man/faces/cat3_psth.png index 1043ed1..808007d 100644 Binary files a/man/faces/cat3_psth.png and b/man/faces/cat3_psth.png differ diff --git a/man/faces/cat5_volume.png b/man/faces/cat5_volume.png index c32dd60..dfee307 100644 Binary files a/man/faces/cat5_volume.png and b/man/faces/cat5_volume.png differ diff --git a/man/faces/cat_contrasts.png b/man/faces/cat_contrasts.png index 43a9476..95d2449 100644 Binary files a/man/faces/cat_contrasts.png and b/man/faces/cat_contrasts.png differ diff --git a/man/faces/cat_design.png b/man/faces/cat_design.png index 87df04e..0d2a48b 100644 Binary files a/man/faces/cat_design.png and b/man/faces/cat_design.png differ diff --git a/man/faces/cat_explore.png b/man/faces/cat_explore.png index 6a4656a..1318564 100644 Binary files a/man/faces/cat_explore.png and b/man/faces/cat_explore.png differ diff --git a/man/faces/command.png b/man/faces/command.png index b5078a6..bf0f4a9 100644 Binary files a/man/faces/command.png and b/man/faces/command.png differ diff --git a/man/faces/coreg.png b/man/faces/coreg.png index 9137389..7ef0ce4 100644 Binary files a/man/faces/coreg.png and b/man/faces/coreg.png differ diff --git a/man/faces/dropout.png b/man/faces/dropout.png index 9a33350..22fbc5c 100644 Binary files a/man/faces/dropout.png and b/man/faces/dropout.png differ diff --git a/man/faces/face_ar1.png b/man/faces/face_ar1.png index 05e16c6..3fadc02 100644 Binary files a/man/faces/face_ar1.png and b/man/faces/face_ar1.png differ diff --git a/man/faces/face_bayes.png b/man/faces/face_bayes.png index 8195fdb..9c560d2 100644 Binary files a/man/faces/face_bayes.png and b/man/faces/face_bayes.png differ diff --git a/man/faces/face_stim.png b/man/faces/face_stim.png index 65ab89f..15938e9 100644 Binary files a/man/faces/face_stim.png and b/man/faces/face_stim.png differ diff --git a/man/faces/face_timing.png b/man/faces/face_timing.png index f491370..ba7e742 100644 Binary files a/man/faces/face_timing.png and b/man/faces/face_timing.png differ diff --git a/man/faces/famous_lag_mip.png b/man/faces/famous_lag_mip.png index 12bbb3d..e50c5f6 100644 Binary files a/man/faces/famous_lag_mip.png and b/man/faces/famous_lag_mip.png differ diff --git a/man/faces/gray.png b/man/faces/gray.png index b1c26fe..12aed78 100644 Binary files a/man/faces/gray.png and b/man/faces/gray.png differ diff --git a/man/faces/movements.png b/man/faces/movements.png index 2792100..44e40ef 100644 Binary files a/man/faces/movements.png and b/man/faces/movements.png differ diff --git a/man/faces/par_design.png b/man/faces/par_design.png index a9832c5..5c0094d 100644 Binary files a/man/faces/par_design.png and b/man/faces/par_design.png differ diff --git a/man/faces/realign.png b/man/faces/realign.png index 590e760..42b0ca4 100644 Binary files a/man/faces/realign.png and b/man/faces/realign.png differ diff --git a/man/faces/smooth.png b/man/faces/smooth.png index b859700..2dce12a 100644 Binary files a/man/faces/smooth.png and b/man/faces/smooth.png differ diff --git a/man/faces_group/Fdisp.png b/man/faces_group/Fdisp.png index 9c6091d..46965db 100644 Binary files a/man/faces_group/Fdisp.png and b/man/faces_group/Fdisp.png differ diff --git a/man/faces_group/Ftemp.png b/man/faces_group/Ftemp.png index 179322b..e68b3b9 100644 Binary files a/man/faces_group/Ftemp.png and b/man/faces_group/Ftemp.png differ diff --git a/man/faces_group/can_weighted_fir.png b/man/faces_group/can_weighted_fir.png index 29ad3c9..0970dd4 100644 Binary files a/man/faces_group/can_weighted_fir.png and b/man/faces_group/can_weighted_fir.png differ diff --git a/man/faces_group/f1_res.png b/man/faces_group/f1_res.png index e8f1550..06dbdd5 100644 Binary files a/man/faces_group/f1_res.png and b/man/faces_group/f1_res.png differ diff --git a/man/faces_group/fir_covariance.png b/man/faces_group/fir_covariance.png index 8195025..7629eb0 100644 Binary files a/man/faces_group/fir_covariance.png and b/man/faces_group/fir_covariance.png differ diff --git a/man/faces_group/fir_design.png b/man/faces_group/fir_design.png index 9aa9daf..59a485e 100644 Binary files a/man/faces_group/fir_design.png and b/man/faces_group/fir_design.png differ diff --git a/man/faces_group/fir_results.png b/man/faces_group/fir_results.png index 39b6e67..a8d8d62 100644 Binary files a/man/faces_group/fir_results.png and b/man/faces_group/fir_results.png differ diff --git a/man/faces_group/informed_covariance.png b/man/faces_group/informed_covariance.png index 068547a..fbc45cd 100644 Binary files a/man/faces_group/informed_covariance.png and b/man/faces_group/informed_covariance.png differ diff --git a/man/faces_group/informed_design.png b/man/faces_group/informed_design.png index 07ac9c6..14cb578 100644 Binary files a/man/faces_group/informed_design.png and b/man/faces_group/informed_design.png differ diff --git a/man/faces_group/informed_plot.png b/man/faces_group/informed_plot.png index 039ae65..b15bd32 100644 Binary files a/man/faces_group/informed_plot.png and b/man/faces_group/informed_plot.png differ diff --git a/man/faces_group/informed_results.png b/man/faces_group/informed_results.png index dfe6d21..92c1a32 100644 Binary files a/man/faces_group/informed_results.png and b/man/faces_group/informed_results.png differ diff --git a/man/faces_group/informed_t.png b/man/faces_group/informed_t.png index e84c926..cfd34a2 100644 Binary files a/man/faces_group/informed_t.png and b/man/faces_group/informed_t.png differ diff --git a/man/faces_group/nullall.png b/man/faces_group/nullall.png index 5fa9cea..ff3a4ff 100644 Binary files a/man/faces_group/nullall.png and b/man/faces_group/nullall.png differ diff --git a/man/faces_group/nullcan.png b/man/faces_group/nullcan.png index 5a5f5c3..1347d62 100644 Binary files a/man/faces_group/nullcan.png and b/man/faces_group/nullcan.png differ diff --git a/man/faces_group/t1.png b/man/faces_group/t1.png index f23221d..83af4ba 100644 Binary files a/man/faces_group/t1.png and b/man/faces_group/t1.png differ diff --git a/man/fmri_est/basis.png b/man/fmri_est/basis.png index dde8478..c4f61e9 100644 Binary files a/man/fmri_est/basis.png and b/man/fmri_est/basis.png differ diff --git a/man/fmri_est/bayes_options.png b/man/fmri_est/bayes_options.png index 56b1375..093b006 100644 Binary files a/man/fmri_est/bayes_options.png and b/man/fmri_est/bayes_options.png differ diff --git a/man/fmri_est/est_method.png b/man/fmri_est/est_method.png index 4a105c5..aa5076e 100644 Binary files a/man/fmri_est/est_method.png and b/man/fmri_est/est_method.png differ diff --git a/man/fmri_spec/design.png b/man/fmri_spec/design.png index a42aa71..518d905 100644 Binary files a/man/fmri_spec/design.png and b/man/fmri_spec/design.png differ diff --git a/man/fmri_spec/fmri_model.png b/man/fmri_spec/fmri_model.png index 57188a5..6d4d97e 100644 Binary files a/man/fmri_spec/fmri_model.png and b/man/fmri_spec/fmri_model.png differ diff --git a/man/fmri_spec/reg4.png b/man/fmri_spec/reg4.png index 46a44a2..4b7ddae 100644 Binary files a/man/fmri_spec/reg4.png and b/man/fmri_spec/reg4.png differ diff --git a/man/manual.tex b/man/manual.tex index a3d84a5..ef553d4 100644 --- a/man/manual.tex +++ b/man/manual.tex @@ -157,7 +157,6 @@ \part{Data sets and examples} \include{auditory/auditory} \include{faces/face} \include{faces_group/face_group} -%\include{fiac} \include{pet/pet} \include{dcm/dcm} \include{ppi/ppi} @@ -173,9 +172,12 @@ \part{Data sets and examples} %%%%%% Appendix %%%%%%% \part{Batch Interface} +\label{Chap:batch_interface} \include{batch/batch} +\include{batch/devel} + %%%%%% BIBLIOGRAPHY %%%%%% \part{Bibliography} diff --git a/man/meeg/eeg_review_buttons.png b/man/meeg/eeg_review_buttons.png index 9910e6c..9f6af83 100644 Binary files a/man/meeg/eeg_review_buttons.png and b/man/meeg/eeg_review_buttons.png differ diff --git a/man/mmn/3DSPM.png b/man/mmn/3DSPM.png index 21f317b..d174c8f 100644 Binary files a/man/mmn/3DSPM.png and b/man/mmn/3DSPM.png differ diff --git a/man/mmn/coreg.png b/man/mmn/coreg.png index d120e2d..e155e87 100644 Binary files a/man/mmn/coreg.png and b/man/mmn/coreg.png differ diff --git a/man/mmn/data_and_design.png b/man/mmn/data_and_design.png index d516663..9545c35 100644 Binary files a/man/mmn/data_and_design.png and b/man/mmn/data_and_design.png differ diff --git a/man/mmn/dcm_gui.png b/man/mmn/dcm_gui.png index 367dded..b119a6b 100644 Binary files a/man/mmn/dcm_gui.png and b/man/mmn/dcm_gui.png differ diff --git a/man/mmn/electro_model.png b/man/mmn/electro_model.png index 036b9b0..6a1eaea 100644 Binary files a/man/mmn/electro_model.png and b/man/mmn/electro_model.png differ diff --git a/man/mmn/erp_c23.png b/man/mmn/erp_c23.png index be35554..991cfd6 100644 Binary files a/man/mmn/erp_c23.png and b/man/mmn/erp_c23.png differ diff --git a/man/mmn/forward.png b/man/mmn/forward.png index 43fc0e6..63ff5fe 100644 Binary files a/man/mmn/forward.png and b/man/mmn/forward.png differ diff --git a/man/mmn/invert.png b/man/mmn/invert.png index b0a4eb1..1f78e81 100644 Binary files a/man/mmn/invert.png and b/man/mmn/invert.png differ diff --git a/man/mmn/mesh.png b/man/mmn/mesh.png index 8a29393..1453e39 100644 Binary files a/man/mmn/mesh.png and b/man/mmn/mesh.png differ diff --git a/man/mmn/neuronal_model.png b/man/mmn/neuronal_model.png index a719516..a9679a7 100644 Binary files a/man/mmn/neuronal_model.png and b/man/mmn/neuronal_model.png differ diff --git a/man/mmn/source_erps.png b/man/mmn/source_erps.png index 1d05c77..30ef4ef 100644 Binary files a/man/mmn/source_erps.png and b/man/mmn/source_erps.png differ diff --git a/man/mmn/source_gui.png b/man/mmn/source_gui.png index 63d0244..c1a419b 100644 Binary files a/man/mmn/source_gui.png and b/man/mmn/source_gui.png differ diff --git a/man/mmn/topo1.png b/man/mmn/topo1.png index 17cec84..773aac1 100644 Binary files a/man/mmn/topo1.png and b/man/mmn/topo1.png differ diff --git a/man/pet/all.png b/man/pet/all.png index 91bad3e..d9336e4 100644 Binary files a/man/pet/all.png and b/man/pet/all.png differ diff --git a/man/pet/all_results.png b/man/pet/all_results.png index a2bc372..d800a39 100644 Binary files a/man/pet/all_results.png and b/man/pet/all_results.png differ diff --git a/man/pet/cluster.png b/man/pet/cluster.png index 48b5db2..9d44ed8 100644 Binary files a/man/pet/cluster.png and b/man/pet/cluster.png differ diff --git a/man/pet/conj.png b/man/pet/conj.png index e94c8a7..7f802dd 100644 Binary files a/man/pet/conj.png and b/man/pet/conj.png differ diff --git a/man/pet/interactive.png b/man/pet/interactive.png index e58a16a..9089f59 100644 Binary files a/man/pet/interactive.png and b/man/pet/interactive.png differ diff --git a/man/pet/masked_con.png b/man/pet/masked_con.png index 70c1601..fd741a9 100644 Binary files a/man/pet/masked_con.png and b/man/pet/masked_con.png differ diff --git a/man/pet/masked_res.png b/man/pet/masked_res.png index 5c3c5d5..d101432 100644 Binary files a/man/pet/masked_res.png and b/man/pet/masked_res.png differ diff --git a/man/pet/multi_design.png b/man/pet/multi_design.png index cc242a8..b3a6f52 100644 Binary files a/man/pet/multi_design.png and b/man/pet/multi_design.png differ diff --git a/man/pet/sc_design.png b/man/pet/sc_design.png index 387de64..603f020 100644 Binary files a/man/pet/sc_design.png and b/man/pet/sc_design.png differ diff --git a/man/pet/single_design.png b/man/pet/single_design.png index f7c810c..8b93c9f 100644 Binary files a/man/pet/single_design.png and b/man/pet/single_design.png differ diff --git a/man/pet/st_design.png b/man/pet/st_design.png index 81f0df3..d18960b 100644 Binary files a/man/pet/st_design.png and b/man/pet/st_design.png differ diff --git a/man/pet/subject2.png b/man/pet/subject2.png index 0dd7bdb..de59364 100644 Binary files a/man/pet/subject2.png and b/man/pet/subject2.png differ diff --git a/man/pet/svc.png b/man/pet/svc.png index ebfdb3c..30e890b 100644 Binary files a/man/pet/svc.png and b/man/pet/svc.png differ diff --git a/man/pet/table.png b/man/pet/table.png index 2512947..2f881b9 100644 Binary files a/man/pet/table.png and b/man/pet/table.png differ diff --git a/man/pet/voi.png b/man/pet/voi.png index 872f0e6..9c36cc0 100644 Binary files a/man/pet/voi.png and b/man/pet/voi.png differ diff --git a/matlabbatch/@cfg_branch/cfg_branch.m b/matlabbatch/@cfg_branch/cfg_branch.m index e1a28ab..205f031 100644 --- a/matlabbatch/@cfg_branch/cfg_branch.m +++ b/matlabbatch/@cfg_branch/cfg_branch.m @@ -50,9 +50,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_branch.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_branch.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4166 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -63,7 +63,7 @@ % assume input is a struct to be converted back into a class % return with error if this does not work if numel(fieldnames(varargin{1})) == numel(fn)+2 && ... - all(isfield(varargin{1}, [fn(:)' {'cfg_item' 'cfg_intree'}])) + all(isfield(varargin{1}, [fn(:)', {'cfg_item' 'cfg_intree'}])) gitem = varargin{1}.cfg_item; sitem = rmfield(varargin{1},{'cfg_item','cfg_intree'}); item = class(sitem, myclass, gitem, cfg_intree); diff --git a/matlabbatch/@cfg_branch/subsasgn.m b/matlabbatch/@cfg_branch/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_branch/subsasgn.m +++ b/matlabbatch/@cfg_branch/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_branch/subsref.m b/matlabbatch/@cfg_branch/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_branch/subsref.m +++ b/matlabbatch/@cfg_branch/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_choice/cfg_choice.m b/matlabbatch/@cfg_choice/cfg_choice.m index 5a74817..0a7a012 100644 --- a/matlabbatch/@cfg_choice/cfg_choice.m +++ b/matlabbatch/@cfg_choice/cfg_choice.m @@ -46,9 +46,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_choice.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_choice.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4166 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -59,7 +59,7 @@ % assume input is a struct to be converted back into a class % return with error if this does not work if numel(fieldnames(varargin{1})) == numel(fn)+2 && ... - all(isfield(varargin{1}, [fn(:)' {'cfg_item' 'cfg_intree'}])) + all(isfield(varargin{1}, [fn(:)', {'cfg_item' 'cfg_intree'}])) gitem = varargin{1}.cfg_item; sitem = rmfield(varargin{1},{'cfg_item','cfg_intree'}); item = class(sitem, myclass, gitem, cfg_intree); diff --git a/matlabbatch/@cfg_choice/subsasgn.m b/matlabbatch/@cfg_choice/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_choice/subsasgn.m +++ b/matlabbatch/@cfg_choice/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_choice/subsref.m b/matlabbatch/@cfg_choice/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_choice/subsref.m +++ b/matlabbatch/@cfg_choice/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_const/cfg_const.m b/matlabbatch/@cfg_const/cfg_const.m index 2198cb6..301bb8a 100644 --- a/matlabbatch/@cfg_const/cfg_const.m +++ b/matlabbatch/@cfg_const/cfg_const.m @@ -46,9 +46,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_const.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_const.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4166 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -59,7 +59,7 @@ % assume input is a struct to be converted back into a class % return with error if this does not work if numel(fieldnames(varargin{1})) == numel(fn)+2 && ... - all(isfield(varargin{1}, [fn(:)' {'cfg_item' 'cfg_leaf'}])) + all(isfield(varargin{1}, [fn(:)', {'cfg_item' 'cfg_leaf'}])) gitem = varargin{1}.cfg_item; sitem = rmfield(varargin{1},{'cfg_item', 'cfg_leaf'}); item = class(sitem, myclass, gitem, cfg_leaf); diff --git a/matlabbatch/@cfg_const/subsasgn.m b/matlabbatch/@cfg_const/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_const/subsasgn.m +++ b/matlabbatch/@cfg_const/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_const/subsref.m b/matlabbatch/@cfg_const/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_const/subsref.m +++ b/matlabbatch/@cfg_const/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_dep/add_to_source.m b/matlabbatch/@cfg_dep/add_to_source.m index ecd8e2f..171fae3 100644 --- a/matlabbatch/@cfg_dep/add_to_source.m +++ b/matlabbatch/@cfg_dep/add_to_source.m @@ -10,16 +10,16 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: add_to_source.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: add_to_source.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 4073 $'; %#ok for k = 1:numel(tdeps) sitem = subsref(cj, tdeps(k).src_exbranch); % Source item to deal with if isempty(sitem.sdeps) sitem.sdeps = tdeps(k); else - sitem.sdeps = [sitem.sdeps(:) tdeps(k)]; + sitem.sdeps = [sitem.sdeps(:)' tdeps(k)]; end; cj = subsasgn(cj, tdeps(k).src_exbranch,sitem); end; diff --git a/matlabbatch/@cfg_dep/subsasgn.m b/matlabbatch/@cfg_dep/subsasgn.m index 3b46b57..c8c9cda 100644 --- a/matlabbatch/@cfg_dep/subsasgn.m +++ b/matlabbatch/@cfg_dep/subsasgn.m @@ -20,112 +20,109 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3792 2010-03-22 13:11:36Z volkmar $ +% $Id: subsasgn.m 4075 2010-10-04 07:36:23Z volkmar $ -rev = '$Rev: 3792 $'; %#ok +rev = '$Rev: 4075 $'; %#ok -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(dep) == nargin-2 - for k = 1:numel(dep) - % input checks - ok = true; - switch subs(1).subs - case {'tname','sname'} - if ~ischar(varargin{k}) - cfg_message('matlabbatch:subsasgn:name', 'Value for field ''%s'' must be a string.', ... - subs(1).subs); - ok = false; - end - case {'tgt_spec'} - if isempty(varargin{k}) - varargin{k} = cfg_findspec; - else - ok = iscell(varargin{k}); - if ok - for l = 1:numel(varargin{k}) - ok = isstruct(varargin{k}{l}) && numel(fieldnames(varargin{k}{l}))==2 ... - && all(isfield(varargin{k}{l},{'name', ... - 'value'})); - if ~ok - break; - end - end - end - if ~ok - cfg_message('matlabbatch:ok_subsasgn:tgt_spec', ... - 'Target specification must be a cfg_findspec.'); - end - end - case subs_fields(dep), - if isempty(varargin{k}) - varargin{k} = struct('type',{}, 'subs',{}); - elseif ~(isstruct(varargin{k}) && isfield(varargin{k},'type') && isfield(varargin{k},'subs')) - cfg_message('matlabbatch:subsasgn:subs', ['Value for field ''%s'' must be a struct with' ... - ' fields ''type'' and ''subs''.'], subs(1).subs); - ok = false; - end - otherwise - cfg_message('matlabbatch:subsasgn:unknownfield', 'Reference to unknown field ''%s''.', subs(1).subs); - end - if ok, - dep(k).(subs(1).subs) = varargin{k}; - end - end - else - cfg_message('matlabbatch:subsasgn:numel', 'In an assignment A.X = B, the number of elements in A and B must be the same.'); - end - case {'()'}, - if isempty(dep) - dep = cfg_dep; - end - dep(subs(1).subs{:}) = varargin{:}; - case {'{}'}, - cfg_message('matlabbatch:subsasgn:notcell', 'Cell content reference from non cell-array object.'); - otherwise - cfg_message('matlabbatch:subsref:unknowntype', 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +persistent my_cfg_dep +sflag = false; +if strcmpi(subs(1).type, '()') + % check array boundaries, extend if necessary + if (numel(subs(1).subs) == 1 && numel(dep) < max(subs(1).subs{1})) || ... + (numel(subs(1).subs) > ndims(dep)) || ... + (numel(subs(1).subs) == ndims(dep) && any(cellfun(@max, subs(1).subs) > size(dep))) + if isempty(my_cfg_dep) + my_cfg_dep = cfg_dep; + end + if isempty(dep) + dep = my_cfg_dep; + end + [dep(subs(1).subs{:})] = deal(my_cfg_dep); + end + if numel(subs) == 1 + return; + else + % select referenced depects from input array, run subsasgn on them an + % put results back into input array + odep = dep; + osubs = subs(1); + dep = dep(subs(1).subs{:}); + subs = subs(2:end); + sflag = true; end - return; end - -%% Canonicalise and check multi-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) >= 2 && strcmp(subs(1).type,'.') - % Canonicalise subs, so that there are two levels within this class - subs = [struct('type','()','subs',{{':'}}) subs]; +if strcmpi(subs(1).type, '.') + % field assignment + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + val = {dep.(subs(1).subs)}; + if nargin == 3 + % Same value to assign to all field values. + val = cellfun(@(cval)subsasgn(cval,subs(2:end),varargin{1}), val, 'UniformOutput', false); + else + % Different values to assign to each field value. + val = cellfun(@(cval,cin)subsasgn(cval,subs(2:end),cin), val, varargin, 'UniformOutput', false); + end + else + % Field values to assign + val = varargin; + end + % Assign to fields + [ok val] = valcheck(subs(1).subs, val); + if ok + if isempty(dep) + dep = repmat(cfg_dep,size(val)); + end + [dep.(subs(1).subs)] = deal(val{:}); + end +else + cfg_message('matlabbatch:subsref:unknowntype', 'Bad subscript type ''%s''.',subs(1).type); end - -if ~strcmp(subs(1).type,'()') - cfg_message('matlabbatch:subsasgn:wrongsubs', 'Wrong subscript reference.'); +if sflag + odep(osubs.subs{:}) = dep; + dep = odep; end -item1 = subsref(dep, subs(1)); -if nargin-2 ~= 1 && nargin-2 ~= numel(item1) - cfg_message('matlabbatch:subsasgn:numel', 'In an assignment A.X = B, the number of elements in A and B must be the same.'); +function [ok val] = valcheck(subs, val) +persistent local_mysubs_fields; +if ~iscell(local_mysubs_fields) + local_mysubs_fields = mysubs_fields; end - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -for k = 1:numel(item1) - if numel(subs) == 2 - if nargin-2 == 1 - item1(k) = subsasgn(item1(k),subs(2),varargin{1}); - else - item1(k) = subsasgn(item1(k),subs(2),varargin{k}); +ok = true; +switch subs + case {'tname','sname'} + if ~all(cellfun(@ischar,val)) + cfg_message('matlabbatch:subsasgn:name', 'Value for field ''%s'' must be a string.', ... + subs); + ok = false; end - else - val = subsref(item1(k), subs(2)); - % explicitly use builtin subsasgn for subscripts into field values - if nargin-2 == 1 - val = builtin('subsasgn',val,subs(3:end),varargin{1}); - else - val = builtin('subsasgn',val,subs(3:end),varargin{k}); + case {'tgt_spec'} + sel = cellfun(@isempty,val); + if any(sel) + [val{sel}] = deal(cfg_findspec); end - item1(k) = subsasgn(item1(k), subs(2), val); - end + ok = all(cellfun(@is_cfg_findspec,val)); + case local_mysubs_fields, + sel = cellfun(@isempty,val); + if any(sel) + [val{sel}] = deal(struct('type',{}, 'subs',{})); + end + ok = all(cellfun(@(cval)(isstruct(cval) && all(isfield(cval,{'type','subs'}))),val)); + if ~ok + cfg_message('matlabbatch:subsasgn:subs', ['Value for field ''%s'' must be a struct with' ... + ' fields ''type'' and ''subs''.'], subs); + end + otherwise + cfg_message('matlabbatch:subsasgn:unknownfield', 'Reference to unknown field ''%s''.', subs); end -dep = subsasgn(dep, subs(1), item1); -return; + +function ok = is_cfg_findspec(fs) +ok = iscell(fs) && ... + all(cellfun(@(cs)(isstruct(cs) && ... + ((numel(fieldnames(cs))==1 && any(isfield(cs,{'name','value'}))) || ... + (numel(fieldnames(cs))==2 && all(isfield(cs,{'name','value'}))))),fs)); +if ~ok + cfg_message('matlabbatch:ok_subsasgn:tgt_spec', ... + 'Target specification must be a cfg_findspec.'); +end \ No newline at end of file diff --git a/matlabbatch/@cfg_dep/subsref.m b/matlabbatch/@cfg_dep/subsref.m index 89febf1..8b2e45e 100644 --- a/matlabbatch/@cfg_dep/subsref.m +++ b/matlabbatch/@cfg_dep/subsref.m @@ -20,43 +20,31 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 4073 $'; %#ok -switch subs(1).type, - case {'.'}, - if numel(subs) > 1 && numel(dep) > 1 - cfg_message('matlabbatch:subsref:multiref', 'Field reference for multiple structure elements that is followed by more reference blocks is an error.'); - end; - switch subs(1).subs - case subs_fields(dep), - val = cell(size(dep)); - for k = 1:numel(dep) - val{k} = dep(k).(subs(1).subs); - end; - otherwise - cfg_message('matlabbatch:subsref:unknownfield', 'Reference to unknown field ''%s''.', subs(1).subs); - end; - case {'()'}, - if numel(subs(1).subs) == 1 % vectorise output - szi = numel(dep); - else % sub-index output - szi = size(dep); - end; - for k = 1:numel(szi) - if ischar(subs(1).subs{k}) && strcmp(subs(1).subs{k},':') - subs(1).subs{k} = 1:szi(k); - end; - end; - val = {dep(subs(1).subs{:})}; - case {'{}'} - cfg_message('matlabbatch:subsref:notcell', 'Cell content reference from non cell-array object.'); - otherwise - cfg_message('matlabbatch:subsref:unknowntype', 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +if strcmpi(subs(1).type, '()') + % select referenced objects from input array + dep = dep(subs(1).subs{:}); + if numel(subs) == 1 + % done, return selected objects + varargout{1} = dep; + return; + else + % continue, avoid recursion + subs = subs(2:end); + end end -if numel(subs) > 1 % in this case, val has only one element, and subs(2:end) are indices into val{1} - val = {builtin('subsref', val{1}, subs(2:end))}; -end; -varargout = val; \ No newline at end of file +if strcmpi(subs(1).type, '.') + % field reference + val = {dep.(subs(1).subs)}; + if numel(subs) > 1 + varargout = cellfun(@(cval)subsref(cval,subs(2:end)), val, 'UniformOutput', false); + else + varargout = val; + end +else + cfg_message('matlabbatch:subsref:unknowntype', 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end \ No newline at end of file diff --git a/matlabbatch/@cfg_entry/cfg_entry.m b/matlabbatch/@cfg_entry/cfg_entry.m index ff5a7d9..9d8f0ea 100644 --- a/matlabbatch/@cfg_entry/cfg_entry.m +++ b/matlabbatch/@cfg_entry/cfg_entry.m @@ -90,9 +90,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_entry.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_entry.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4166 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -103,7 +103,7 @@ % assume input is a struct to be converted back into a class % return with error if this does not work if numel(fieldnames(varargin{1})) == numel(fn)+2 && ... - all(isfield(varargin{1}, [fn(:)' {'cfg_item' 'cfg_leaf'}])) + all(isfield(varargin{1}, [fn(:)', {'cfg_item' 'cfg_leaf'}])) gitem = varargin{1}.cfg_item; sitem = rmfield(varargin{1},{'cfg_item', 'cfg_leaf'}); item = class(sitem, myclass, gitem, cfg_leaf); diff --git a/matlabbatch/@cfg_entry/subsasgn.m b/matlabbatch/@cfg_entry/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_entry/subsasgn.m +++ b/matlabbatch/@cfg_entry/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_entry/subsasgn_check.m b/matlabbatch/@cfg_entry/subsasgn_check.m index 07757a5..33aa0cb 100644 --- a/matlabbatch/@cfg_entry/subsasgn_check.m +++ b/matlabbatch/@cfg_entry/subsasgn_check.m @@ -11,9 +11,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn_check.m 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsasgn_check.m 4089 2010-10-11 11:53:34Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 4089 $'; %#ok sts = true; switch subs(1).subs @@ -66,13 +66,10 @@ end if isa(val,'cfg_dep') % Check dependency match - sts2 = false(size(val)); - for k = 1:numel(val) - sts2(k) = match(item, val(k).tgt_spec); - if ~sts2(k) - cfg_message('matlabbatch:checkval', ... - '%s: Dependency does not match.', subsasgn_checkstr(item,subs)); - end + sts2 = cellfun(@(cspec)match(item,cspec),{val.tgt_spec}); + if ~all(sts2) + cfg_message('matlabbatch:checkval', ... + '%s: Dependency does not match.', subsasgn_checkstr(item,subs)); end val = val(sts2); sts = any(sts2); diff --git a/matlabbatch/@cfg_entry/subsref.m b/matlabbatch/@cfg_entry/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_entry/subsref.m +++ b/matlabbatch/@cfg_entry/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_exbranch/display.m b/matlabbatch/@cfg_exbranch/display.m new file mode 100644 index 0000000..8461583 --- /dev/null +++ b/matlabbatch/@cfg_exbranch/display.m @@ -0,0 +1,21 @@ +function display(item) + +% function display(item) +% Display a configuration object +% +% This code is part of a batch job configuration system for MATLAB. See +% help matlabbatch +% for a general overview. +%_______________________________________________________________________ +% Copyright (C) 2007 Freiburg Brain Imaging + +% Volkmar Glauche +% $Id: display.m 4166 2011-01-17 15:06:41Z volkmar $ + +rev = '$Rev: 4166 $'; %#ok + +disp(' '); +disp([inputname(1),' = ']); +disp(' '); +disp(item); +disp(' '); diff --git a/matlabbatch/@cfg_exbranch/subsasgn.m b/matlabbatch/@cfg_exbranch/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_exbranch/subsasgn.m +++ b/matlabbatch/@cfg_exbranch/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_exbranch/subsref.m b/matlabbatch/@cfg_exbranch/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_exbranch/subsref.m +++ b/matlabbatch/@cfg_exbranch/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_files/cfg_files.m b/matlabbatch/@cfg_files/cfg_files.m index 1095681..7c9a1bf 100644 --- a/matlabbatch/@cfg_files/cfg_files.m +++ b/matlabbatch/@cfg_files/cfg_files.m @@ -69,9 +69,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_files.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_files.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4166 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -82,7 +82,7 @@ % assume input is a struct to be converted back into a class % return with error if this does not work if numel(fieldnames(varargin{1})) == numel(fn)+2 && ... - all(isfield(varargin{1}, [fn(:)' {'cfg_item' 'cfg_leaf'}])) + all(isfield(varargin{1}, [fn(:)', {'cfg_item' 'cfg_leaf'}])) gitem = varargin{1}.cfg_item; sitem = rmfield(varargin{1},{'cfg_item', 'cfg_leaf'}); item = class(sitem, myclass, gitem, cfg_leaf); diff --git a/matlabbatch/@cfg_files/subsasgn.m b/matlabbatch/@cfg_files/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_files/subsasgn.m +++ b/matlabbatch/@cfg_files/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_files/subsasgn_check.m b/matlabbatch/@cfg_files/subsasgn_check.m index fb68df7..2f931c1 100644 --- a/matlabbatch/@cfg_files/subsasgn_check.m +++ b/matlabbatch/@cfg_files/subsasgn_check.m @@ -12,9 +12,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn_check.m 2539 2008-12-09 11:19:55Z volkmar $ +% $Id: subsasgn_check.m 4089 2010-10-11 11:53:34Z volkmar $ -rev = '$Rev: 2539 $'; %#ok +rev = '$Rev: 4089 $'; %#ok sts = true; switch subs(1).subs @@ -62,14 +62,13 @@ end val = {val1}; elseif isa(val{1}, 'cfg_dep') + % {val{1}.tgt_spec} does not seem to work properly + cval = val{1}; % Check dependency match - sts2 = false(size(val{1})); - for k = 1:numel(val{1}) - sts2(k) = match(item, val{1}(k).tgt_spec); - if ~sts2(k) - cfg_message('matlabbatch:checkval', ... - '%s: Dependency does not match.', subsasgn_checkstr(item,subs)); - end + sts2 = cellfun(@(cspec)match(item,cspec),{cval.tgt_spec}); + if ~all(sts2) + cfg_message('matlabbatch:checkval', ... + '%s: Dependency does not match.', subsasgn_checkstr(item,subs)); end val{1} = val{1}(sts2); sts = any(sts2); diff --git a/matlabbatch/@cfg_files/subsref.m b/matlabbatch/@cfg_files/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_files/subsref.m +++ b/matlabbatch/@cfg_files/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_item/subsasgn.m b/matlabbatch/@cfg_item/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_item/subsasgn.m +++ b/matlabbatch/@cfg_item/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_item/subsref.m b/matlabbatch/@cfg_item/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_item/subsref.m +++ b/matlabbatch/@cfg_item/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_menu/cfg_menu.m b/matlabbatch/@cfg_menu/cfg_menu.m index 9802deb..010a47e 100644 --- a/matlabbatch/@cfg_menu/cfg_menu.m +++ b/matlabbatch/@cfg_menu/cfg_menu.m @@ -46,9 +46,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_menu.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_menu.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4166 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -59,7 +59,7 @@ % assume input is a struct to be converted back into a class % return with error if this does not work if numel(fieldnames(varargin{1})) == numel(fn)+2 && ... - all(isfield(varargin{1}, [fn(:)' {'cfg_item' 'cfg_leaf'}])) + all(isfield(varargin{1}, [fn(:)', {'cfg_item' 'cfg_leaf'}])) gitem = varargin{1}.cfg_item; sitem = rmfield(varargin{1},{'cfg_item', 'cfg_leaf'}); item = class(sitem, myclass, gitem, cfg_leaf); diff --git a/matlabbatch/@cfg_menu/subsasgn.m b/matlabbatch/@cfg_menu/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_menu/subsasgn.m +++ b/matlabbatch/@cfg_menu/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_menu/subsref.m b/matlabbatch/@cfg_menu/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_menu/subsref.m +++ b/matlabbatch/@cfg_menu/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/@cfg_repeat/cfg_repeat.m b/matlabbatch/@cfg_repeat/cfg_repeat.m index 9b3ad4c..25923c7 100644 --- a/matlabbatch/@cfg_repeat/cfg_repeat.m +++ b/matlabbatch/@cfg_repeat/cfg_repeat.m @@ -59,9 +59,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_repeat.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_repeat.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4166 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -72,7 +72,7 @@ % assume input is a struct to be converted back into a class % return with error if this does not work if numel(fieldnames(varargin{1})) == numel(fn)+2 && ... - all(isfield(varargin{1}, [fn(:)' {'cfg_item' 'cfg_intree'}])) + all(isfield(varargin{1}, [fn(:)', {'cfg_item' 'cfg_intree'}])) gitem = varargin{1}.cfg_item; sitem = rmfield(varargin{1},{'cfg_item','cfg_intree'}); item = class(sitem, myclass, gitem, cfg_intree); diff --git a/matlabbatch/@cfg_repeat/initialise.m b/matlabbatch/@cfg_repeat/initialise.m index c84fc69..9c6c005 100644 --- a/matlabbatch/@cfg_repeat/initialise.m +++ b/matlabbatch/@cfg_repeat/initialise.m @@ -21,9 +21,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: initialise.m 3591 2009-11-23 10:19:57Z volkmar $ +% $Id: initialise.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3591 $'; %#ok +rev = '$Rev: 4073 $'; %#ok if strcmp(val,'') item = initialise_def(item, val, dflag); @@ -51,9 +51,11 @@ if dflag item.values{1} = initialise(item.values{1}, val, dflag); else + citem = cell(1,numel(val)); for k = 1:numel(val) - item.cfg_item.val{k} = initialise(item.values{1}, val(k), dflag); + citem{k} = initialise(item.values{1}, val(k), dflag); end; + item.cfg_item.val = citem; end; else cfg_message('matlabbatch:initialise', ... @@ -99,13 +101,14 @@ item.values{1} = initialise(item.values{1}, val{1}, dflag); end; else + citem = cell(1,numel(val)); if numel(item.values) > 1 || item.forcestruct for l = 1:numel(val) % val{l} should be a struct with a single field vtag = fieldnames(val{l}); for k = 1:numel(item.values) if strcmp(gettag(item.values{k}), vtag{1}) - item.cfg_item.val{l} = initialise(item.values{k}, ... + citem{l} = initialise(item.values{k}, ... val{l}.(vtag{1}), ... dflag); end; @@ -113,10 +116,11 @@ end; else for l = 1:numel(val) - item.cfg_item.val{l} = initialise(item.values{1}, ... + citem{l} = initialise(item.values{1}, ... val{l}, dflag); end; end; + item.cfg_item.val = citem; end; end; diff --git a/matlabbatch/@cfg_repeat/subsasgn.m b/matlabbatch/@cfg_repeat/subsasgn.m index 4424009..fdf523d 100644 --- a/matlabbatch/@cfg_repeat/subsasgn.m +++ b/matlabbatch/@cfg_repeat/subsasgn.m @@ -32,9 +32,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsasgn.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -61,80 +61,48 @@ 'Arrays of cfg_item objects not supported.'); end; -%% One-level subscripts -%-------------------------------------------------------------------------- -if numel(subs) == 1 - switch subs(1).type, - case {'.'}, - if numel(item) == 1 && nargin == 3 - [ok val] = subsasgn_check(item,subs,varargin{1}); - if ok, - switch subs(1).subs - case par_fields, - item.(par_class) = subsasgn(item.(par_class), subs, val); - case local_mysubs_fields, - item.(subs(1).subs) = val; - otherwise - cfg_message('matlabbatch:subsasgn', ... - ['Reference to unknown field ''%s''.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs, subs(1).subs); - end; - end; +switch subs(1).type, + case {'.'}, + if numel(item) == 1 && nargin == 3 + if numel(subs) > 1 + % Only part of field value(s) assigned. Get old field value(s), + % assign values to it. + if any(strcmp(subs(1).subs,par_fields)) + val0 = item.(par_class).(subs(1).subs); + else + val0 = item.(subs(1).subs); + end + val1 = cfg_callbuiltin('subsasgn',val0,subs(2:end),varargin{1}); else - cfg_message('matlabbatch:subsasgn', ... - ['Array assignments not supported for fields of cfg_item objects.\n' ... - 'To assign to a field in the job structure, use a reference like ' ... - '''(x).%s''.'], subs(1).subs); - + % Field values to assign + val1 = varargin{1}; + end + [ok val] = subsasgn_check(item,subs,val1); + if ok, + switch subs(1).subs + case par_fields, + item.(par_class).(subs(1).subs) = val; + case local_mysubs_fields, + item.(subs(1).subs) = val; + otherwise + cfg_message('matlabbatch:subsasgn', ... + ['Reference to unknown field ''%s''.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs, subs(1).subs); + end; end; - case {'()','{}'}, + else cfg_message('matlabbatch:subsasgn', ... - 'Subscript type ''%s'' reserved for future use.', subs(1).type); - otherwise - cfg_message('matlabbatch:subsasgn', ... - 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); - end; - return; -end; - -%% Two- and multi-level subscripts -%-------------------------------------------------------------------------- -item = subsasgn_rec(item, subs, varargin{1}); -return; + ['Array assignments not supported for fields of cfg_item objects.\n' ... + 'To assign to a field in the job structure, use a reference like ' ... + '''(x).%s''.'], subs(1).subs); -function it = subsasgn_rec(it, subs, val) -if numel(subs) == 1 - % final subscript - try - it = builtin('subsasgn', it, subs, val); - catch - % there may be an object method that is missed by builtin - it = subsasgn(it, subs, val); - end; -else - try - it1 = subsref(it, subs(1)); - catch - % it does not yet contain contents at this subscript - % builtin subsasgn will be clever enough to create the necessary - % struct/fields that are referenced - it = builtin('subsasgn', it, subs, val); - return; - end; - it1 = subsasgn_rec(it1, subs(2:end), val); - % try - % do we need this? - % it = builtin('subsasgn', it, subs(1), it1); - %catch - if isobject(it) - try - % try to use class subsasgn - it = subsasgn(it,subs(1), it1); - catch - it = builtin('subsasgn', it, subs(1), it1); end; - else - it = builtin('subsasgn', it, subs(1), it1); - end; -end; \ No newline at end of file + case {'()','{}'}, + cfg_message('matlabbatch:subsasgn', ... + 'Subscript type ''%s'' reserved for future use.', subs(1).type); + otherwise + cfg_message('matlabbatch:subsasgn', ... + 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); +end; +return; \ No newline at end of file diff --git a/matlabbatch/@cfg_repeat/subsref.m b/matlabbatch/@cfg_repeat/subsref.m index 02c14bc..945a1be 100644 --- a/matlabbatch/@cfg_repeat/subsref.m +++ b/matlabbatch/@cfg_repeat/subsref.m @@ -23,9 +23,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: subsref.m 4073 2010-09-24 12:07:57Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4073 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -55,30 +55,23 @@ end; switch subs(1).subs case local_mysubs_fields, - val = {item.(subs(1).subs)}; + val = item.(subs(1).subs); case par_fields, - val = {item.(par_class).(subs(1).subs)}; + val = item.(par_class).(subs(1).subs); otherwise cfg_message('matlabbatch:subsref:unknownfield', ... ['Reference to unknown field ''%s''.\nTo reference ' ... 'a field in the job structure, use a reference like ' ... '''(x).%s'''], subs(1).subs, subs(1).subs); end; - if numel(subs) > 1 - % in this case, val has only one element, and - % subs(2:end) are indices into val{1} - % val = {builtin('subsref', val{1}, subs(2:end))}; - % The line above does not seem to work, as MATLAB is - % not able to figure out which subsref to call and when. - for k = 2:numel(subs) - val = {subsref(val{1}, subs(k))}; - end; - end; - case {'()','{}'}, - val = subsref_job(item, subs, false); + if numel(subs) > 1 + val = cfg_callbuiltin('subsref',val,subs(2:end)); + end +% case {'()','{}'}, +% val = subsref_job(item, subs, false); otherwise cfg_message('matlabbatch:subsref:unknowntype', ... 'Unknown subsref type: ''%s''. This should not happen.', subs(1).type); end -varargout = val; \ No newline at end of file +varargout = {val}; \ No newline at end of file diff --git a/matlabbatch/cfg_basicio/cfg_run_file_move.m b/matlabbatch/cfg_basicio/cfg_run_file_move.m index 4f7e8af..a5ff642 100644 --- a/matlabbatch/cfg_basicio/cfg_run_file_move.m +++ b/matlabbatch/cfg_basicio/cfg_run_file_move.m @@ -11,23 +11,30 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_run_file_move.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_run_file_move.m 4102 2010-10-28 10:47:15Z volkmar $ -rev = '$Rev: 3944 $'; %#ok +rev = '$Rev: 4102 $'; %#ok action = fieldnames(job.action); action = action{1}; if strcmp(action, 'delete') + todelete = {}; for k = 1:numel(job.files) [p n e] = fileparts(job.files{k}); if numel(e)>=4 && any(strcmp(e(1:4), {'.nii','.img'})) try [p n e v] = spm_fileparts(job.files{k}); - delete(fullfile(p,[n '.hdr'])); - delete(fullfile(p,[n '.mat'])); + todelete{end+1} = fullfile(p,[n '.hdr']); + todelete{end+1} = fullfile(p,[n '.mat']); end end - delete(fullfile(p, [n e])); + todelete{end+1} = fullfile(p, [n e]); + end + if ~isempty(todelete) + ws = warning; + warning off; + delete(todelete{:}); + warning(ws); end out = []; else diff --git a/matlabbatch/cfg_callbuiltin.m b/matlabbatch/cfg_callbuiltin.m new file mode 100644 index 0000000..3e8545c --- /dev/null +++ b/matlabbatch/cfg_callbuiltin.m @@ -0,0 +1,11 @@ +function varargout = cfg_callbuiltin(varargin) +if nargout == 0 + try + varargout{1} = builtin(varargin{:}); + catch + builtin(varargin{:}); + end +else + varargout = cell(1,nargout); + [varargout{:}] = builtin(varargin{:}); +end diff --git a/matlabbatch/cfg_getfile.m b/matlabbatch/cfg_getfile.m index bc9a898..3d14d91 100644 --- a/matlabbatch/cfg_getfile.m +++ b/matlabbatch/cfg_getfile.m @@ -85,7 +85,7 @@ % Copyright (C) 2007 Freiburg Brain Imaging % John Ashburner and Volkmar Glauche -% $Id: cfg_getfile.m 3944 2010-06-23 08:53:40Z volkmar $ +% $Id: cfg_getfile.m 4176 2011-01-27 14:34:44Z volkmar $ t = {}; sts = false; @@ -255,9 +255,8 @@ if ~isempty(fg) delete(fg); end -% create temporary figure to work out position etc. -% seems to be necessary -fgtmp = figure('IntegerHandle','off',... +% create figure +fg = figure('IntegerHandle','off',... 'Tag',mfilename,... 'Name',mesg,... 'NumberTitle','off',... @@ -267,30 +266,8 @@ 'DefaultUicontrolInterruptible','on',... 'Visible','off'); -Rect = get(fgtmp,'Position'); -delete(fgtmp); -%S0 = spm('WinSize','0',1); -S0 = get(0,'MonitorPosition'); -if size(S0,1) > 1 % Multiple Monitors - %-Use Monitor containing the Pointer - pl = get(0,'PointerLocation'); - w = find(pl(1)>=S0(:,1) & pl(1)=S0(:,2) & pl(2) 2 && cfg_util('ismod_job_id',varargin{1},varargin{2}) + cjob = varargin{1}; + cmod = varargin{2}; + varargout{1} = {subsref(jobs(cjob).cj, [jobs(cjob).cjid2subs{cmod} substruct('.','sout')])}; else varargout{1} = {}; end @@ -630,13 +637,15 @@ varargout{2} = {}; return; elseif ischar(varargin{1}) || iscellstr(varargin{1}) - job = cfg_load_jobs(varargin{1}); + [job jobdedup] = cfg_load_jobs(varargin{1}); elseif iscell(varargin{1}) && iscell(varargin{1}{1}) % try to initialise cell array of jobs job = varargin{1}; + jobdedup = NaN; % Postpone duplicate detection else % try to initialise single job job{1} = varargin{1}; + jobdedup = 1; end % job should be a cell array of job structures isjob = true(size(job)); @@ -647,8 +656,26 @@ if isempty(job) cfg_message('matlabbatch:initialise:invalid','No valid job.'); else + if any(isnan(jobdedup)) + % build up list of unique jobs + jobdedup = NaN*ones(size(job)); + cu = 0; + for k = 1:numel(job) + if isnan(jobdedup(k)) + % found new candidate + cu = cu+1; + jobdedup(k) = cu; + % look for similar jobs under remaining candidates + csel = find(isnan(jobdedup)); + eqind = cellfun(@(cjob)isequalwithequalnans(cjob,job{k}),job(csel)); + jobdedup(csel(eqind)) = cu; + end + end + else + jobdedup = jobdedup(isjob); + end jobs(cjob).c0 = c0; - [jobs(cjob) mod_job_idlist] = local_initjob(jobs(cjob), job); + [jobs(cjob) mod_job_idlist] = local_initjob(jobs(cjob), job, jobdedup); varargout{1} = cjob; varargout{2} = mod_job_idlist; end @@ -786,8 +813,11 @@ varargin{3}], cm); end end + % clear run configuration + jobs(cjob).cjrun = []; + jobs(cjob).cjid2subsrun = {}; end - case {'run','runserial'} + case {'run','runserial','cont','contserial'} if cfg_util('isjob_id',varargin{1}) cjob = varargin{1}; dflag = false; @@ -795,12 +825,9 @@ cjob = cfg_util('initjob',varargin{1}); dflag = true; end - if strcmpi(cmd, 'run') - pflag = cfg_get_defaults([mfilename '.runparallel']); - else - pflag = false; - end - [jobs(cjob) err] = local_runcj(jobs(cjob), cjob, pflag); + pflag = any(strcmpi(cmd, {'run','cont'})) && cfg_get_defaults([mfilename '.runparallel']); + cflag = any(strcmpi(cmd, {'cont','contserial'})); + [jobs(cjob) err] = local_runcj(jobs(cjob), cjob, pflag, cflag); if dflag cfg_util('deljob', cjob); end @@ -849,9 +876,10 @@ cm = setval(cm, varargin{4}, false); jobs(cjob).cj = subsasgn(jobs(cjob).cj, [jobs(cjob).cjid2subs{mod_job_id}, item_mod_id], cm); varargout{1} = all_set_item(cm); + % clear run configuration + jobs(cjob).cjrun = []; + jobs(cjob).cjid2subsrun = {}; end - % clear run configuration - jobs(cjob).cjrun = []; case 'showdoc', if nargin == 2 % get item from defaults tree @@ -955,6 +983,7 @@ jobs(k).c0.values{end+1} = c1; % clear run configuration jobs(k).cjrun = []; + jobs(k).cjid2subsrun = {}; end cfg_message('matlabbatch:cfg_util:addapp:done', 'Added application ''%s''\n', c1.name); %----------------------------------------------------------------------- @@ -994,6 +1023,7 @@ job.cjid2subs{id} = cjsubs; % clear run configuration job.cjrun = []; +job.cjid2subsrun = {}; %----------------------------------------------------------------------- %----------------------------------------------------------------------- @@ -1001,7 +1031,8 @@ % Try to work around some unexpected behaviour of MATLAB's cd command if ~isempty(pth) if ischar(pth) - wd = cd(pth); + wd = pwd; + cd(pth); else cfg_message('matlabbatch:usage','CD: path must be a string.'); end @@ -1049,6 +1080,9 @@ if any(cid) job.cj = update_deps(job.cj, oid(cid), job.cjid2subs(cid)); end +% clear run configuration +job.cjrun = []; +job.cjid2subsrun = {}; %----------------------------------------------------------------------- %----------------------------------------------------------------------- @@ -1082,6 +1116,7 @@ job.cjid2subs{id} = struct([]); % clear run configuration job.cjrun = []; +job.cjid2subsrun = {}; %----------------------------------------------------------------------- %----------------------------------------------------------------------- @@ -1314,65 +1349,59 @@ function local_gencode(c0, fname, tropts, preamble) %----------------------------------------------------------------------- %----------------------------------------------------------------------- -function [cjob, mod_job_idlist] = local_initjob(cjob, job) +function [cjob, mod_job_idlist] = local_initjob(cjob, job, jobdedup) % Initialise a cell array of jobs -for n = 1:numel(job) - % update application defaults - not only in .values, but also in - % pre-configured .val items - cj1 = initialise(cjob.c0, '', false); - % init job - cj1 = initialise(cj1, job{n}, false); - % canonicalise (this may break dependencies, see comment in - % local_getcjid2subs) - [cj1 cjid2subs1] = local_getcjid2subs(cj1); - % harvest, keeping dependencies - [u1 u2 u3 u4 u5 cj1] = harvest(cj1, cj1, false, false); - if n == 1 - cjob.cj = cj1; - cjob.cjid2subs = cjid2subs1; - else - cjidoffset = numel(cjob.cjid2subs); - cjid2subs2 = cjid2subs1; - idsubs = substruct('.','id'); - sdsubs = substruct('.','sdeps'); - v1subs = substruct('.','val','{}',{1}); - for k = 1:numel(cjid2subs2) - % update id subscripts - cjid2subs2{k}(2).subs{1} = cjid2subs2{k}(2).subs{1} + cjidoffset; - cj1 = subsasgn(cj1, [cjid2subs1{k}, idsubs], ... - cjid2subs2{k}); - % update src_exbranch in dependent cfg_items - sdeps = subsref(cj1, [cjid2subs1{k}, sdsubs]); - for l = 1:numel(sdeps) - % dependent module - dm = subsref(cj1, sdeps(l).tgt_exbranch); - % delete old tdeps - needs to be updated by harvest - dm.tdeps = []; - % dependencies in dependent item - ideps = subsref(dm, ... - [sdeps(l).tgt_input v1subs]); - for m = 1:numel(ideps) - % find reference that matches old source id - if isequal(ideps(m).src_exbranch, cjid2subs1{k}) - ideps(m).src_exbranch = cjid2subs2{k}; - end - end - % save updated item - dm = subsasgn(dm, ... - [sdeps(l).tgt_input v1subs], ... - ideps); - % save updated module - cj1 = subsasgn(cj1, sdeps(l).tgt_exbranch, dm); - end - % done with sdeps - clear - cj1 = subsasgn(cj1, [cjid2subs1{k}, sdsubs], []); - end - % concatenate configs - cjob.cjid2subs = [cjob.cjid2subs cjid2subs2]; - for k = 1:numel(cj1.val) - cjob.cj.val{end+1} = cj1.val{k}; +idsubs = substruct('.','id'); +sdsubs = substruct('.','sdeps'); +tdsubs = substruct('.','tdeps'); +v1subs = substruct('.','val','{}',{1}); +% Update application defaults - not only in .values, but also in +% pre-configured .val items. Use this as template for all jobs. +cjd = initialise(cjob.c0, '', false); +% Prepare all jobs - initialise similar jobs only once. +[ujobdedup ui uj] = unique(jobdedup); +% Initialise jobs +ucj = cellfun(@(ucjob)initialise(cjd,ucjob,false), job(ui), 'UniformOutput', false); +% Canonicalise (this may break dependencies, see comment in +% local_getcjid2subs) +[ucj ucjid2subs] = cellfun(@local_getcjid2subs, ucj, 'UniformOutput', false); +% Harvest, keeping dependencies +[u1 u2 u3 u4 u5 ucj] = cellfun(@(cucj)harvest(cucj, cucj, false, false), ucj, 'UniformOutput', false); +% Deduplicate, concatenate +cjob.cj = ucj{uj(1)}; +cjob.cjid2subs = ucjid2subs{uj(1)}; +for n = 2:numel(uj) + cjidoffset = numel(cjob.cjid2subs); + cj1 = ucj{uj(n)}; + cjid2subs1 = ucjid2subs{uj(n)}; + cjid2subs2 = ucjid2subs{uj(n)}; + for k = 1:numel(cjid2subs2) + % update id subscripts + cjid2subs2{k}(2).subs{1} = cjid2subs2{k}(2).subs{1} + cjidoffset; + cj1 = subsasgn(cj1, [cjid2subs1{k}, idsubs], ... + cjid2subs2{k}); + % update src_exbranch in dependent cfg_items + sdeps = subsref(cj1, [cjid2subs1{k}, sdsubs]); + for l = 1:numel(sdeps) + csdep = sdeps(l); + tgt_exbranch = csdep.tgt_exbranch; + tgt_input = [csdep.tgt_input v1subs]; + % dependencies in dependent item + ideps = subsref(cj1, [tgt_exbranch tgt_input]); + isel = cellfun(@(iid)isequal(iid,cjid2subs1{k}),{ideps.src_exbranch}); + ideps(isel).src_exbranch = cjid2subs2{k}; + % save updated item & module + cj1 = subsasgn(cj1, [tgt_exbranch tgt_input], ... + ideps); + % delete old tdeps - needs to be updated by harvest + cj1 = subsasgn(cj1, [tgt_exbranch tdsubs], []); end + % done with sdeps - clear + cj1 = subsasgn(cj1, [cjid2subs1{k}, sdsubs], []); end + % concatenate configs + cjob.cjid2subs = [cjob.cjid2subs cjid2subs2]; + cjob.cj.val = [cjob.cj.val cj1.val]; end % harvest, update dependencies [u1 u2 u3 u4 u5 cjob.cj] = harvest(cjob.cj, cjob.cj, false, false); @@ -1407,10 +1436,11 @@ function local_gencode(c0, fname, tropts, preamble) job.cjid2subs{id} = rcjsubs; % clear run configuration job.cjrun = []; +job.cjid2subsrun = {}; %----------------------------------------------------------------------- %----------------------------------------------------------------------- -function [job err] = local_runcj(job, cjob, pflag) +function [job err] = local_runcj(job, cjob, pflag, cflag) % Matlab uses a copy-on-write policy with very high granularity - if % modified, only parts of a struct or cell array are copied. % However, forward resolution may lead to high memory consumption if @@ -1423,19 +1453,22 @@ function local_gencode(c0, fname, tropts, preamble) % If pflag is true, then modules will be executed in parallel if they are % independent. Setting pflag to false forces serial execution of modules % even if they seem to be independent. -% If a job with pre-set module outputs .jout is passed in cj, the -% corresponding modules will not be run again. This feature is currently unused. +% If cflag is true, and a job with pre-set module outputs .jout is passed +% in job.cjrun, the corresponding modules will not be run again. cfg_message('matlabbatch:run:jobstart', ... ['\n\n------------------------------------------------------------------------\n',... 'Running job #%d\n', ... '------------------------------------------------------------------------'], cjob); - -job1 = local_compactjob(job); +if cflag && ~isempty(job.cjrun) + [u1 mlbch] = harvest(job.cjrun, job.cjrun, false, true); +else + job1 = local_compactjob(job); + job.cjid2subsrun = job1.cjid2subs; + [u1 mlbch u3 u4 u5 job.cjrun] = harvest(job1.cj, job1.cj, false, true); +end % copy cjid2subs, it will be modified for each module that is run -cjid2subs = job1.cjid2subs; -job.cjid2subsrun = job1.cjid2subs; -[u1 mlbch u3 u4 u5 job.cjrun] = harvest(job1.cj, job1.cj, false, true); +cjid2subs = job.cjid2subsrun; cjid2subsfailed = {}; cjid2subsskipped = {}; tdsubs = substruct('.','tdeps'); @@ -1529,6 +1562,11 @@ function local_gencode(c0, fname, tropts, preamble) str{numel(cjid2subsfailed)+k+1} = sprintf('Skipped: %s', ... subsref(job.cjrun, [cjid2subsskipped{k} substruct('.','name')])); end +% Commented out for SPM public release +% str{end+1} = sprintf(['If the problem can be fixed without modifying ' ... +% 'the job, the computation can be resumed by ' ... +% 'running\n cfg_util(''cont'',%d)\nfrom the ' ... +% 'MATLAB command line.'],cjob); cfg_message('matlabbatch:run:jobfailed', '%s\n', str{:}); err.identifier = 'matlabbatch:run:jobfailederr'; err.message = sprintf(['Job execution failed. The full log of this run can ' ... diff --git a/matlabbatch/private/cfg_load_jobs.m b/matlabbatch/private/cfg_load_jobs.m new file mode 100644 index 0000000..74f2cec --- /dev/null +++ b/matlabbatch/private/cfg_load_jobs.m @@ -0,0 +1,69 @@ +function [newjobs uind] = cfg_load_jobs(job) + +% function newjobs = cfg_load_jobs(job) +% +% Load a list of possible job files, return a cell list of jobs. +% +% This code is part of a batch job configuration system for MATLAB. See +% help matlabbatch +% for a general overview. +%_______________________________________________________________________ +% Copyright (C) 2007 Freiburg Brain Imaging + +% Volkmar Glauche +% $Id: cfg_load_jobs.m 4150 2011-01-07 14:41:56Z volkmar $ + +rev = '$Rev: 4150 $'; %#ok + +if ischar(job) + filenames = cellstr(job); +else + filenames = job; +end; +[ufilenames unused uind] = unique(filenames); +ujobs = cell(size(ufilenames)); +usts = false(size(ufilenames)); +for cf = 1:numel(ufilenames) + [ujobs{cf} usts(cf)] = load_single_job(ufilenames{cf}); +end +sts = usts(uind); +uind = uind(sts); +newjobs = ujobs(uind); + +function [matlabbatch sts] = load_single_job(filename) +[p,nam,ext] = fileparts(filename); +switch ext + case '.xml', + try + loadxml(filename,'matlabbatch'); + catch + cfg_message('matlabbatch:initialise:xml','LoadXML failed: ''%s''',filename); + end; + case '.mat' + try + S=load(filename); + matlabbatch = S.matlabbatch; + catch + cfg_message('matlabbatch:initialise:mat','Load failed: ''%s''',filename); + end; + case '.m' + try + fid = fopen(filename,'rt'); + str = fread(fid,'*char'); + fclose(fid); + eval(str); + catch + cfg_message('matlabbatch:initialise:m','Eval failed: ''%s''',filename); + end; + if ~exist('matlabbatch','var') + cfg_message('matlabbatch:initialise:m','No matlabbatch job found in ''%s''', filename); + end; + otherwise + cfg_message('matlabbatch:initialise:unknown','Unknown extension: ''%s''', filename); +end; +if exist('matlabbatch','var') + sts = true; +else + sts = false; + matlabbatch = []; +end; diff --git a/matlabbatch/private/cfg_mlbatch_defaults.m b/matlabbatch/private/cfg_mlbatch_defaults.m index 38107ca..f728d6d 100644 --- a/matlabbatch/private/cfg_mlbatch_defaults.m +++ b/matlabbatch/private/cfg_mlbatch_defaults.m @@ -11,26 +11,30 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_mlbatch_defaults.m 3792 2010-03-22 13:11:36Z volkmar $ +% $Id: cfg_mlbatch_defaults.m 4166 2011-01-17 15:06:41Z volkmar $ -rev = '$Rev: 3792 $'; %#ok +rev = '$Rev: 4166 $'; %#ok -% Font definition for cfg_ui user interface -% cfg_defaults.cfg_ui.Xfont is a font struct as returned by uisetfont -% lfont: used in lists, value edit dialogues etc. -cfg_defaults.cfg_ui.lfont.FontAngle = 'normal'; -cfg_defaults.cfg_ui.lfont.FontName = get(0,'factoryTextFontName'); -cfg_defaults.cfg_ui.lfont.FontSize = 12; -cfg_defaults.cfg_ui.lfont.FontUnits = 'points'; -cfg_defaults.cfg_ui.lfont.FontWeight = 'normal'; -% bfont: used for buttons -cfg_defaults.cfg_ui.bfont.FontAngle = get(0, 'factoryUicontrolFontAngle'); -cfg_defaults.cfg_ui.bfont.FontName = get(0,'factoryUicontrolFontName'); -cfg_defaults.cfg_ui.bfont.FontSize = get(0, 'factoryUicontrolFontSize'); -cfg_defaults.cfg_ui.bfont.FontUnits = get(0, 'factoryUicontrolFontUnits'); -cfg_defaults.cfg_ui.bfont.FontWeight = get(0, 'factoryUicontrolFontWeight'); -% Toggle ExpertEdit mode. Value can be 'on' or 'off' -cfg_defaults.cfg_ui.ExpertEdit = 'off'; +try + % Font definition for cfg_ui user interface + % cfg_defaults.cfg_ui.Xfont is a font struct as returned by uisetfont + % lfont: used in lists, value edit dialogues etc. + cfg_defaults.cfg_ui.lfont.FontAngle = 'normal'; + cfg_defaults.cfg_ui.lfont.FontName = get(0,'factoryTextFontName'); + cfg_defaults.cfg_ui.lfont.FontSize = 12; + cfg_defaults.cfg_ui.lfont.FontUnits = 'points'; + cfg_defaults.cfg_ui.lfont.FontWeight = 'normal'; + % bfont: used for buttons + cfg_defaults.cfg_ui.bfont.FontAngle = get(0, 'factoryUicontrolFontAngle'); + cfg_defaults.cfg_ui.bfont.FontName = get(0,'factoryUicontrolFontName'); + cfg_defaults.cfg_ui.bfont.FontSize = get(0, 'factoryUicontrolFontSize'); + cfg_defaults.cfg_ui.bfont.FontUnits = get(0, 'factoryUicontrolFontUnits'); + cfg_defaults.cfg_ui.bfont.FontWeight = get(0, 'factoryUicontrolFontWeight'); + % Toggle ExpertEdit mode. Value can be 'on' or 'off' + cfg_defaults.cfg_ui.ExpertEdit = 'off'; +catch + cfg_defaults.cfg_ui = false; +end % cfg_util % Parallel execution of independent modules @@ -120,4 +124,4 @@ % configuration has been initialised to speed up job % initialisation/harvest/run - set this to true if you want to debug some % configuration or the batch system itself -cfg_defaults.cfg_item.checkval = false; \ No newline at end of file +cfg_defaults.cfg_item.checkval = false; diff --git a/matlabbatch/private/cfg_onscreen.m b/matlabbatch/private/cfg_onscreen.m new file mode 100644 index 0000000..5a34690 --- /dev/null +++ b/matlabbatch/private/cfg_onscreen.m @@ -0,0 +1,37 @@ +function varargout = cfg_onscreen(fg) +% Move figure on the screen containing the mouse +% cfg_onscreen(fg) - move figure fg on the screen containing the mouse +% pos = cfg_onscreen(fg) - compute position of figure, do not move it +% +% This code is part of a batch job configuration system for MATLAB. See +% help matlabbatch +% for a general overview. +%_______________________________________________________________________ +% Copyright (C) 2007 Freiburg Brain Imaging + +% Volkmar Glauche +% $Id: cfg_onscreen.m 4033 2010-08-04 15:53:35Z volkmar $ + +rev = '$Rev: 4033 $'; + +% save figure units - use pixels here +units = get(fg,'Units'); +set(fg,'Units','pixels'); +Rect = get(fg,'Position'); +S0 = get(0,'MonitorPosition'); +if size(S0,1) > 1 % Multiple Monitors + %-Use Monitor containing the Pointer + pl = get(0,'PointerLocation'); + w = find(pl(1)>=S0(:,1) & pl(1)=S0(:,2) & pl(2) 0 && ReDo) v = struct('Name','','Version','','Release','','Date',''); try - fid = fopen(fullfile(spm('Dir'),'Contents.m'),'rt'); + if isdeployed + % in deployed mode, M-files are encrypted + % (even if first two lines of Contents.m "should" be preserved) + vfile = fullfile(spm('Dir'),'Contents.txt'); + else + vfile = fullfile(spm('Dir'),'Contents.m'); + end + fid = fopen(vfile,'rt'); if fid == -1, error(str); end l1 = fgetl(fid); l2 = fgetl(fid); fclose(fid); @@ -1157,16 +1185,7 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality v.Name = l1; v.Date = t{4}; v.Version = t{2}; v.Release = t{3}(2:end-1); catch - if isdeployed - % in deployed mode, M-files are encrypted - % (but first two lines of Contents.m should be preserved) - v.Name = 'Statistical Parametric Mapping'; - v.Version = '8'; - v.Release = 'SPM8'; - v.Date = date; - else - error('Can''t obtain SPM Revision information.'); - end + error('Can''t obtain SPM Revision information.'); end SPM_VER = v; end diff --git a/spm_ADEM.m b/spm_ADEM.m index 2a7365c..3a5b182 100644 --- a/spm_ADEM.m +++ b/spm_ADEM.m @@ -38,6 +38,8 @@ % M(i).V = fixed precision (input noise) % M(i).W = fixed precision (state noise) % M(i).xP = precision (states) +% +% M(1).Ra = indices of prediction errors driving action % % M(i).m = number of inputs v(i + 1); % M(i).n = number of states x(i) @@ -112,7 +114,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_ADEM.m 3901 2010-05-27 16:14:36Z karl $ +% $Id: spm_ADEM.m 4230 2011-03-07 20:58:38Z karl $ % check model, data, priors and unpack %-------------------------------------------------------------------------- @@ -567,7 +569,7 @@ for i = 1:nh iS = iS + Q{i}*exp(qh.h(i)); end - S = inv(iS); + S = spm_inv(iS); dS = ECE + EE - S*nY; % 1st-order derivatives: dFdh = dF/dh @@ -637,8 +639,10 @@ z = spm_unvec(pU(t).z{1},{G.v}); w = spm_unvec(pU(t).w{1},{G.x}); for i = 1:nl - PU.v{i}(:,t) = spm_vec(v{i}); - PU.z{i}(:,t) = spm_vec(z{i}); + try + PU.v{i}(:,t) = spm_vec(v{i}); + PU.z{i}(:,t) = spm_vec(z{i}); + end try PU.x{i}(:,t) = spm_vec(x{i}); PU.w{i}(:,t) = spm_vec(w{i}); diff --git a/spm_Bcdf.m b/spm_Bcdf.m index 3be87b4..a170bb5 100644 --- a/spm_Bcdf.m +++ b/spm_Bcdf.m @@ -12,7 +12,7 @@ % distributions. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The Beta distribution has two shape parameters, v and w, and is % defined for v>0 & w>0 and for x in [0,1] (See Evans et al., Ch5). % The Cumulative Distribution Function (CDF) F(x) is the probability @@ -22,15 +22,15 @@ % definitions of the incomplete beta function. % % Variate relationships: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Many: See Evans et al., Ch5 % % Algorithm: -%----------------------------------------------------------------------- -% Using Matlab's implementation of the incomplete beta finction (betainc). +%-------------------------------------------------------------------------- +% Using MATLAB's implementation of the incomplete beta finction (betainc). % % References: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Evans M, Hastings N, Peacock B (1993) % "Statistical Distributions" % 2nd Ed. Wiley, New York @@ -43,37 +43,39 @@ % "Numerical Recipes in C" % Cambridge %__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% Copyright (C) 1999-2011 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_Bcdf.m 1143 2008-02-07 19:33:33Z spm $ - +% $Id: spm_Bcdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Format arguments, note & check sizes -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<3, error('Insufficient arguments'), end ad = [ndims(x);ndims(v);ndims(w)]; rd = max(ad); -as = [ [size(x),ones(1,rd-ad(1))];... - [size(v),ones(1,rd-ad(2))];... - [size(w),ones(1,rd-ad(3))] ]; +as = [[size(x),ones(1,rd-ad(1))];... + [size(v),ones(1,rd-ad(2))];... + [size(w),ones(1,rd-ad(3))]]; rs = max(as); xa = prod(as,2)>1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) - error('non-scalar args must match in size'), end +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) + error('non-scalar args must match in size'); +end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros F = zeros(rs); %-Only defined for x in [0,1] & strictly positive v & w. % Return NaN if undefined. md = ( x>=0 & x<=1 & v>0 & w>0 ); -if any(~md(:)), F(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + F(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-Special cases: F=1 when x=1 F(md & x==1) = 1; diff --git a/spm_Bpdf.m b/spm_Bpdf.m index 810f5b3..af0e4ec 100644 --- a/spm_Bpdf.m +++ b/spm_Bpdf.m @@ -11,7 +11,7 @@ % spm_Bpdf implements the Probability Density Function for Beta distributions. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The PDF of the Beta distribution shape parameters v & w, defined % for positive integer degrees of freedom v>0 & w>0, and for x in % [0,1] is given by: (See Evans et al., Ch5) @@ -21,16 +21,16 @@ % beta(v,w) % % Variate relationships: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Many: See Evans et al., Ch5 % % Algorithm: -%----------------------------------------------------------------------- -% Direct computation using logs and Matlab's implementation of the log +%-------------------------------------------------------------------------- +% Direct computation using logs and MATLAB's implementation of the log % beta function (betaln). % % References: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Evans M, Hastings N, Peacock B (1993) % "Statistical Distributions" % 2nd Ed. Wiley, New York @@ -43,37 +43,39 @@ % "Numerical Recipes in C" % Cambridge %__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% Copyright (C) 1999-2011 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_Bpdf.m 1143 2008-02-07 19:33:33Z spm $ - +% $Id: spm_Bpdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Format arguments, note & check sizes -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<3, error('Insufficient arguments'), end ad = [ndims(x);ndims(v);ndims(w)]; rd = max(ad); -as = [ [size(x),ones(1,rd-ad(1))];... - [size(v),ones(1,rd-ad(2))];... - [size(w),ones(1,rd-ad(3))] ]; +as = [[size(x),ones(1,rd-ad(1))];... + [size(v),ones(1,rd-ad(2))];... + [size(w),ones(1,rd-ad(3))]]; rs = max(as); xa = prod(as,2)>1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) - error('non-scalar args must match in size'), end +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) + error('non-scalar args must match in size'); +end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros f = zeros(rs); %-Only defined for x in [0,1] & strictly positive v & w. % Return NaN if undefined. md = ( x>=0 & x<=1 & v>0 & w>0 ); -if any(~md(:)), f(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + f(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-Special cases: x=0 & x=1 f(md & x==0 & v<1) = Inf; diff --git a/spm_DEM.m b/spm_DEM.m index 9960879..6d174ec 100644 --- a/spm_DEM.m +++ b/spm_DEM.m @@ -42,7 +42,7 @@ %-------------------------------------------------------------------------- % qP.P = Conditional expectation % qP.C = Conditional covariance -% +% % conditional moments of hyper-parameters (log-transformed) - q(h) %-------------------------------------------------------------------------- % qH.h = Conditional expectation (cause noise) @@ -63,9 +63,9 @@ % E: qp.p = max q(u,h) % M: qh.h = max q(u,p) % -% where qu.u corresponds to the conditional expectation of hidden states x -% and causal states v and so on. L is the ln p(y,u,p,h|M) under the model -% M. The conditional covariances obtain analytically from the curvature of +% where qu.u corresponds to the conditional expectation of hidden states x +% and causal states v and so on. L is the ln p(y,u,p,h|M) under the model +% M. The conditional covariances obtain analytically from the curvature of % L with respect to u, p and h. % % The D-step is embedded in the E-step because q(u) changes with each @@ -73,13 +73,13 @@ % model using temporal derivatives at each time point. Continuity of the % conditional trajectories q(u,t) is assured by a continuous ascent of F(t) % in generalised co-ordinates. This means DEM can deconvolve online and can -% represents an alternative to Kalman filtering or alternative Bayesian +% represents an alternative to Kalman filtering or alternative Bayesian % update procedures. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM.m 3977 2010-07-08 14:14:35Z karl $ +% $Id: spm_DEM.m 4146 2010-12-23 21:01:39Z karl $ % check model, data, priors and confounds and unpack %-------------------------------------------------------------------------- @@ -91,11 +91,7 @@ % tolerance for changes in norm %-------------------------------------------------------------------------- -TOL = 1e-3; - -% enable mean field effects -%-------------------------------------------------------------------------- -mf = 1; +TOL = exp(-4); % order parameters (d = n = 1 for static models) and checks %========================================================================== @@ -114,12 +110,11 @@ % number of iterations %-------------------------------------------------------------------------- -try nD = M(1).E.nD; catch nD = 1; end -try nE = M(1).E.nE; catch nE = 1; end -try nM = M(1).E.nM; catch nM = 8; end -try nN = M(1).E.nN; catch nN = 16; end -try K = M(1).E.K; catch K = 1; end - +try nD = M(1).E.nD; catch nD = 1; end +try nE = M(1).E.nE; catch nE = 8; end +try nM = M(1).E.nM; catch nM = 8; end +try K = M(1).E.K; catch K = 1; end + % initialise regularisation parameters %-------------------------------------------------------------------------- @@ -128,11 +123,12 @@ else td = {8}; end -if M(1).E.linear - te = 8; % integration time for E-Step +if M(1).E.linear == 1 + te = 4; % integration time for E-Step else - te = 4; + te = 0; end +tm = 4; % integration time for M-Step % precision components Q{} requiring [Re]ML estimators (M-Step) %========================================================================== @@ -145,12 +141,12 @@ W0 = kron(sparse(n,n),spm_cat(w0)); Qp = blkdiag(V0,W0); for i = 1:nl - + % precision (R) and covariance of generalised errors %---------------------------------------------------------------------- iVv = spm_DEM_R(n,M(i).sv); iVw = spm_DEM_R(n,M(i).sw); - + % noise on causal states (Q) %---------------------------------------------------------------------- for j = 1:length(M(i).Q) @@ -158,13 +154,13 @@ q{i,i} = M(i).Q{j}; Q{end + 1} = blkdiag(kron(iVv,spm_cat(q)),W0); end - + % and fixed components (V) %---------------------------------------------------------------------- q = v0; q{i,i} = M(i).V; Qp = Qp + blkdiag(kron(iVv,spm_cat(q)),W0); - + % noise on hidden states (R) %---------------------------------------------------------------------- for j = 1:length(M(i).R) @@ -172,7 +168,7 @@ q{i,i} = M(i).R{j}; Q{end + 1} = blkdiag(V0,kron(iVw,spm_cat(q))); end - + % and fixed components (W) %---------------------------------------------------------------------- q = w0; @@ -200,21 +196,21 @@ ph.c = spm_cat(spm_diag({M.hC M.gC})); % prior covariances of h qh.h = ph.h; % conditional expectation qh.c = ph.c; % conditional covariance -ph.ic = spm_pinv(ph.c); % prior precision +ph.ic = spm_pinv(ph.c); % prior precision % priors on parameters (in reduced parameter space) %========================================================================== pp.c = cell(nl,nl); qp.p = cell(nl,1); for i = 1:(nl - 1) - + % eigenvector reduction: p <- pE + qp.u*qp.p %---------------------------------------------------------------------- qp.u{i} = spm_svd(M(i).pC,exp(-32)); % basis for parameters M(i).p = size(qp.u{i},2); % number of qp.p qp.p{i} = sparse(M(i).p,1); % initial qp.p pp.c{i,i} = qp.u{i}'*M(i).pC*qp.u{i}; % prior covariance - + end Up = spm_cat(spm_diag(qp.u)); @@ -224,25 +220,26 @@ nb = size(X,1); % number of confounds nn = nb*ny; % number of nuisance parameters nf = np + nn; % number of free parameters -ip = [1:np]; -ib = [1:nn] + np; +ip = (1:np); +ib = (1:nn) + np; pp.c = spm_cat(pp.c); pp.ic = spm_inv(pp.c); +pp.p = spm_vec(qp.p); -% initialise conditional density q(p) (for D-Step) +% initialise conditional density q(p) := qp.e (for D-Step) %-------------------------------------------------------------------------- for i = 1:(nl - 1) try qp.e{i} = qp.p{i} + qp.u{i}'*(spm_vec(M(i).P) - spm_vec(M(i).pE)); catch - qp.e{i} = qp.p{i}; % initial qp.e + qp.e{i} = qp.p{i}; end -end +end qp.e = spm_vec(qp.e); qp.c = sparse(nf,nf); qp.b = sparse(ny,nb); - - + + % initialise dedb %-------------------------------------------------------------------------- for i = 1:nl @@ -285,11 +282,11 @@ Dy = kron(spm_speye(n,n,1),spm_speye(ny,ny,0)); Dc = kron(spm_speye(d,d,1),spm_speye(nc,nc,0)); D = spm_cat(spm_diag({Dx,Dv,Dy,Dc})); - + % and null blocks %-------------------------------------------------------------------------- dVdy = sparse(n*ny,1); -dVdc = sparse(d*nc,1); +dVdc = sparse(d*nc,1); dVdyy = sparse(n*ny,n*ny); dVdcc = sparse(d*nc,d*nc); @@ -300,323 +297,257 @@ dWduu = sparse(nu,nu); dWdpp = sparse(nf,nf); -% preclude unneceassry iterations +% preclude unnecessary iterations %-------------------------------------------------------------------------- if ~nh, nM = 1; end -if ~nf, nE = 1; end -if ~nf && ~nh, nN = 1; end +if ~nf && ~nh, nE = 1; end + +% preclude very precise states from entering free-energy/action +%-------------------------------------------------------------------------- +ix = (1:(nx*n)) + ny*n + nv*n; +iv = (1:(nv*d)) + ny*n; +je = diag(Qp) < exp(16); +ju = [je(ix); je(iv)]; -% Iterate DEM + +% E-Step: (with embedded D and M-Steps) %========================================================================== Fi = -Inf; -for iN = 1:nN +for iE = 1:nE % get time and celar persistent variables in evaluation routines %---------------------------------------------------------------------- - tic; clear spm_DEM_eval - - % E-Step: (with embedded D-Step) + tic; clear spm_DEM_eval + + % [re-]set accumulators for E-Step + %---------------------------------------------------------------------- + dFdh = sparse(nh,1); % gradient (hyperparamteres) + dFdhh = sparse(nh,nh); % curvatiure (hyperparamteres) + dFdp = sparse(nf,1); % gradient (paramteres) + dFdpp = sparse(nf,nf); % curvatiure (paramteres) + qp.ic = sparse(0); % conditional precision (p) + iqu.c = sparse(0); % conditional information (p) + EE = sparse(0); + ECE = sparse(0); + + % [re-]set precisions using ReML hyperparameter estimates + %---------------------------------------------------------------------- + iS = Qp; + for i = 1:nh + iS = iS + Q{i}*exp(qh.h(i)); + end + + % [re-]adjust for confounds + %---------------------------------------------------------------------- + Y = Y - qp.b*X; + + % [re-]set states & their derivatives + %---------------------------------------------------------------------- + try, qu = qU(1); end + + % D-Step: (nD D-Steps for each sample) %====================================================================== - mp = 0; % cumulator for changes in p - Fe = -exp(64); % Free energy (E-stpep) - for iE = 1:nE - - - % [re-]set accumulators for E-Step - %------------------------------------------------------------------ - spm_logdet_qu_c = 0; - dFdp = zeros(nf,1); - dFdpp = zeros(nf,nf); - EE = sparse(0); - ECE = sparse(0); - qp.ic = sparse(0); - - % [re-]set precisions using ReML hyperparameter estimates - %------------------------------------------------------------------ - iS = Qp; - for i = 1:nh - iS = iS + Q{i}*exp(qh.h(i)); - end + for iY = 1:nY - % [re-]adjust for confounds + % [re-]set states for static systems %------------------------------------------------------------------ - Y = Y - qp.b*X; + if ~nx, try, qu = qU(iY); end, end - % [re-]set states & their derivatives - %------------------------------------------------------------------ - try - qu = qU(1); - end - - % D-Step: (nD D-Steps for each sample) + % D-Step: until convergence for static systems %================================================================== - for iY = 1:nY - - % [re-]set states for static systems + Fd = -exp(64); + for iD = 1:nD + + % sampling time %-------------------------------------------------------------- - if ~nx - try, qu = qU(iY); end + ts = iY + (iD - 1)/nD; + + % derivatives of responses and inputs + %-------------------------------------------------------------- + try + qu.y(1:n) = spm_DEM_embed(Y,n,ts,1,M(1).delays); + qu.u(1:d) = spm_DEM_embed(U,d,ts); + catch + qu.y(1:n) = spm_DEM_embed(Y,n,ts); + qu.u(1:d) = spm_DEM_embed(U,d,ts); end - - % D-Step: until convergence for static systems + + % compute dEdb (derivatives of confounds) + %-------------------------------------------------------------- + b = spm_DEM_embed(X,n,ts); + for i = 1:n + dedbi{1} = -kron(b{i}',speye(ny,ny)); + dEdb{i,1} = spm_cat(dedbi); + end + + % evaluate functions: + % E = v - g(x,v) and derivatives dE.dx, ... %============================================================== - Fd = -exp(64); - for iD = 1:nD - - % sampling time - %---------------------------------------------------------- - ts = iY + (iD - 1)/nD; - - % derivatives of responses and inputs - %---------------------------------------------------------- - try - qu.y(1:n) = spm_DEM_embed(Y,n,ts,1,M(1).delays); - qu.u(1:d) = spm_DEM_embed(U,d,ts); - catch - qu.y(1:n) = spm_DEM_embed(Y,n,ts); - qu.u(1:d) = spm_DEM_embed(U,d,ts); - end - - % compute dEdb (derivatives of confounds) - %---------------------------------------------------------- - b = spm_DEM_embed(X,n,ts); - for i = 1:n - dedbi{1} = -kron(b{i}',speye(ny,ny)); - dEdb{i,1} = spm_cat(dedbi); - end - - % evaluate functions: - % E = v - g(x,v) and derivatives dE.dx, ... - %========================================================== - [E dE] = spm_DEM_eval(M,qu,qp); + [E dE] = spm_DEM_eval(M,qu,qp); + + % conditional covariance [of states {u}] + %-------------------------------------------------------------- + qu.p = dE.du'*iS*dE.du + Pu; + qu.c = diag(ju)*spm_inv(qu.p)*diag(ju); + iqu.c = iqu.c + spm_logdet(qu.c); + + % and conditional covariance [of parameters {P}] + %-------------------------------------------------------------- + dE.dP = spm_cat({dE.dp dEdb}); + ECEu = dE.du*qu.c*dE.du'; + ECEp = dE.dP*qp.c*dE.dP'; + + if ~nx - % conditional covariance [of states {u}] - %---------------------------------------------------------- - qu.p = dE.du'*iS*dE.du + Pu; - qu.c = spm_inv(qu.p); - spm_logdet_qu_c = spm_logdet_qu_c + spm_logdet(qu.c); - - % and conditional covariance [of parameters {P}] + % Evaluate objective function L(t) (for static models) %---------------------------------------------------------- - dE.dP = spm_cat({dE.dp dEdb}); - ECEu = dE.du*qu.c*dE.du'; - ECEp = dE.dP*qp.c*dE.dP'; + L = - trace(E'*iS*E)/2 ... % states (u) + - trace(iS*ECEp)/2; % expectation q(p) - % Evaluate objective function L(t) (for static models) + % if F is increasing, save expansion point %---------------------------------------------------------- - if ~nx + if L > Fd + td = {min(td{1} + 1, 8)}; + Fd = L; + B.qu = qu; + B.E = E; + B.dE = dE; + B.ECEp = ECEp; - L = - trace(E'*iS*E)/2 ... % states (u) - - trace(iS*ECEp)/2; % expectation q(p) - - % if F is increasing, save expansion point + else + + % otherwise, return to previous expansion point %------------------------------------------------------ - if L > Fd - td = {min(td{1} + 1,+8)}; - Fd = L; - B.qu = qu; - B.E = E; - B.dE = dE; - B.ECEp = ECEp; - - else - - % otherwise, return to previous expansion point - %-------------------------------------------------- - qu = B.qu; - E = B.E; - dE = B.dE; - ECEp = B.ECEp; - td = {min(td{1} - 2,-4)}; - end - end - - % save states at qu(t) - %---------------------------------------------------------- - if iD == 1 - qE{iY} = E; - qU(iY) = qu; - end - - - % uncertainty about parameters dWdv, ... ; W = ln(|qp.c|) - %========================================================== - if np && mf - for i = 1:nu - CJp(:,i) = spm_vec(qp.c(ip,ip)*dE.dpu{i}'*iS); - dEdpu(:,i) = spm_vec(dE.dpu{i}'); - end - dWdu = CJp'*spm_vec(dE.dp'); - dWduu = CJp'*dEdpu; - end - - - % D-step update: of causes v{i}, and hidden states x(i) - %========================================================== - - % conditional modes - %---------------------------------------------------------- - q = {qu.x{1:n} qu.v{1:d} qu.y{1:n} qu.u{1:d}}; - u = spm_vec(q); - - % first-order derivatives - %---------------------------------------------------------- - dVdu = -dE.du'*iS*E - dWdu/2 - Pu*u(1:nu); - - % and second-order derivatives - %---------------------------------------------------------- - dVduu = -dE.du'*iS*dE.du - dWduu/2 - Pu; - dVduy = -dE.du'*iS*dE.dy; - dVduc = -dE.du'*iS*dE.dc; - - % gradient - %---------------------------------------------------------- - dFdu = spm_vec({dVdu; dVdy; dVdc }); - - % Jacobian (variational flow) - %---------------------------------------------------------- - dFduu = spm_cat({dVduu dVduy dVduc ; - [] dVdyy [] ; - [] [] dVdcc}); - - - % update conditional modes of states - %========================================================== - f = K*dFdu + D*u; - dfdu = K*dFduu + D; - du = spm_dx(dfdu,f,td); - q = spm_unvec(u + du,q); - - % and save them - %---------------------------------------------------------- - qu.x(1:n) = q([1:n]); - qu.v(1:d) = q([1:d] + n); - - - % D-Step: break if convergence (for static models) - %---------------------------------------------------------- - if ~nx - qU(iY) = qu; - end - if ~nx && ((dFdu'*du < 1e-2) || (norm(du,1) < TOL)) - break - end - - % report (D-Steps) - %----------------------------------------------------------- - if ~nx && nY < 8 - str{1} = sprintf('D-Step: %i (%i)',iD,iY); - str{2} = sprintf('I:%.6e',full(Fd)); - str{3} = sprintf('u:%.2e',full(du'*du)); - fprintf('%-16s%-24s%-16s\n',str{1:3}) + qu = B.qu; + E = B.E; + dE = B.dE; + ECEp = B.ECEp; + td = {min(td{1} - 2,-4)}; end - - end % D-Step + end - % Gradients and curvatures for E-Step: W = tr(C*J'*iS*J) + % save states at qu(t) + %-------------------------------------------------------------- + if iD == 1 + qE{iY} = E; + qU(iY) = qu; + end + + + % uncertainty about parameters dWdv, ... ; W = ln(|qp.c|) %============================================================== - if np && mf - for i = ip - CJu(:,i) = spm_vec(qu.c*dE.dup{i}'*iS); - dEdup(:,i) = spm_vec(dE.dup{i}'); + if np + for i = 1:nu + CJp(:,i) = spm_vec(qp.c(ip,ip)*dE.dpu{i}'*iS); + dEdpu(:,i) = spm_vec(dE.dpu{i}'); end - dWdp(ip) = CJu'*spm_vec(dE.du'); - dWdpp(ip,ip) = CJu'*dEdup; + dWdu = CJp'*spm_vec(dE.dp'); + dWduu = CJp'*dEdpu; end - - - % Accumulate; dF/dP =
, dF/dpp = ... + + + % D-step update: of causes v{i}, and hidden states x(i) + %============================================================== + + % conditional modes %-------------------------------------------------------------- - dFdp = dFdp - dWdp/2 - dE.dP'*iS*E; - dFdpp = dFdpp - dWdpp/2 - dE.dP'*iS*dE.dP; - qp.ic = qp.ic + dE.dP'*iS*dE.dP; - - % and quantities for M-Step + q = {qu.x{1:n} qu.v{1:d} qu.y{1:n} qu.u{1:d}}; + u = spm_vec(q); + + % first-order derivatives %-------------------------------------------------------------- - EE = E*E'+ EE; - if mf - ECE = ECE + ECEu + ECEp; - end + dVdu = -dE.du'*iS*E - dWdu/2 - Pu*u(1:nu); - end % sequence (nY) - - % augment with priors - %------------------------------------------------------------------ - dFdp(ip) = dFdp(ip) - pp.ic*qp.e; - dFdpp(ip,ip) = dFdpp(ip,ip) - pp.ic; - qp.ic(ip,ip) = qp.ic(ip,ip) + pp.ic; - qp.c = spm_inv(qp.ic); - - % evaluate objective function - %================================================================== - L = - trace(iS*EE)/2 ... % states (u) - - trace(qp.e'*pp.ic*qp.e)/2; % parameters (p) - - - % if F is increasing, save expansion point and derivatives - %------------------------------------------------------------------ - if L > Fe || iN == 1 + % and second-order derivatives + %-------------------------------------------------------------- + dVduu = -dE.du'*iS*dE.du - dWduu/2 - Pu; + dVduy = -dE.du'*iS*dE.dy; + dVduc = -dE.du'*iS*dE.dc; + + % gradient + %-------------------------------------------------------------- + dFdu = spm_vec({dVdu; dVdy; dVdc }); - Fe = L; - te = min(te + 1,+8); - B.dFdp = dFdp; - B.dFdpp = dFdpp; - B.qp = qp; - B.mp = mp; + % Jacobian (variational flow) + %-------------------------------------------------------------- + dFduu = spm_cat({dVduu dVduy dVduc ; + [] dVdyy [] ; + [] [] dVdcc}); - else - % otherwise, return to previous expansion point + % update conditional modes of states + %============================================================== + f = K*dFdu + D*u; + dfdu = K*dFduu + D; + du = spm_dx(dfdu,f,td); + q = spm_unvec(u + du,q); + + % and save them %-------------------------------------------------------------- - dFdp = B.dFdp; - dFdpp = B.dFdpp; - qp = B.qp; - mp = B.mp; - te = min(te - 2,-4); - end - - % E-step: update expectation (p) + qu.x(1:n) = q([1:n]); + qu.v(1:d) = q([1:d] + n); + + + % D-Step: break if convergence (for static models) + %-------------------------------------------------------------- + if ~nx + qU(iY) = qu; + end + if ~nx && ((dFdu'*du < TOL) || (norm(du,1) < TOL)) + break + end + + end % D-Step + + % Gradients and curvatures for E-Step: W = tr(C*J'*iS*J) %================================================================== - - % update conditional expectation + if np + for i = ip + CJu(:,i) = spm_vec(qu.c*dE.dup{i}'*iS); + dEdup(:,i) = spm_vec(dE.dup{i}'); + end + dWdp(ip) = CJu'*spm_vec(dE.du'); + dWdpp(ip,ip) = CJu'*dEdup; + end + + + % Accumulate; dF/dP =
, dF/dpp = ... %------------------------------------------------------------------ - dp = spm_dx(dFdpp,dFdp,{te}); - qp.e = qp.e + dp(ip); - qp.p = spm_unvec(qp.e,qp.p); - qp.b = spm_unvec(dp(ib),qp.b); - mp = mp + dp; - - % convergence (E-Step) + dFdp = dFdp - dWdp/2 - dE.dP'*iS*E; + dFdpp = dFdpp - dWdpp/2 - dE.dP'*iS*dE.dP; + qp.ic = qp.ic + dE.dP'*iS*dE.dP; + + % and quantities for M-Step %------------------------------------------------------------------ - if (dFdp'*dp < 1e-2) || (norm(dp,1) < TOL), break, end + EE = E*E'+ EE; + ECE = ECE + ECEu + ECEp; + - end % E-Step + end % sequence (nY) - % M-step - hyperparameters (h = exp(l)) + % M-step - optimise hyperparameters (mh = total update) %====================================================================== - mh = zeros(nh,1); - dFdh = zeros(nh,1); - dFdhh = zeros(nh,nh); + mh = 0; for iM = 1:nM - + % [re-]set precisions using ReML hyperparameter estimates %------------------------------------------------------------------ iS = Qp; for i = 1:nh - iS = iS + Q{i}*exp(qh.h(i)); + iS = iS + Q{i}*exp(qh.h(i)); end S = spm_inv(iS); dS = ECE + EE - S*nY; - + % 1st-order derivatives: dFdh = dF/dh %------------------------------------------------------------------ for i = 1:nh - dPdh{i} = Q{i}*exp(qh.h(i)); + dPdh{i} = Q{i}*exp(qh.h(i)); dFdh(i,1) = -trace(dPdh{i}*dS)/2; end - + % 2nd-order derivatives: dFdhh %------------------------------------------------------------------ for i = 1:nh @@ -633,123 +564,157 @@ % update ReML estimate of parameters %------------------------------------------------------------------ - dh = spm_dx(dFdhh,dFdh,{4}); + dh = spm_dx(dFdhh,dFdh,{tm}); + dh = max(min(dh,2),-2); qh.h = qh.h + dh; mh = mh + dh; % conditional covariance of hyperparameters %------------------------------------------------------------------ qh.c = -spm_inv(dFdhh); - + % convergence (M-Step) %------------------------------------------------------------------ - if (dFdh'*dh < 1e-2) || (norm(dh,1) < TOL), break, end + if (dFdh'*dh < TOL) || (norm(dh,1) < TOL), break, end end % M-Step + + % conditional precision of parameters + %------------------------------------------------------------------ + qp.ic(ip,ip) = qp.ic(ip,ip) + pp.ic; + qp.c = spm_inv(qp.ic); + % evaluate objective function (F) %====================================================================== - Lu = - trace(iS*EE)/2 - n*ny*log(2*pi)*nY/2 ... % states (u) - + spm_logdet(iS)*nY/2 ... % entropy - error - + spm_logdet_qu_c/(2*nD); % entropy q(u) - - Lp = - trace(qp.e'*pp.ic*qp.e)/2 ... % parameters (p) - - trace(qh.e'*ph.ic*qh.e)/2 ... % hyperparameters (h) - + spm_logdet(qp.c)/2 ... % entropy q(p) - + spm_logdet(qh.c)/2 ... % entropy q(h) - - spm_logdet(pp.c)/2 ... % entropy - prior p - - spm_logdet(ph.c)/2; % entropy - prior h - - La = - trace(qp.e'*pp.ic*qp.e)*nY/2 ... % parameters (p) - - trace(qh.e'*ph.ic*qh.e)*nY/2 ... % hyperparameters (h) - + spm_logdet(qp.c*nY)*nY/2 ... % entropy q(p) - + spm_logdet(qh.c*nY)*nY/2 ... % entropy q(h) - - spm_logdet(pp.c)*nY/2 ... % entropy - prior p - - spm_logdet(ph.c)*nY/2; % entropy - prior h - - Li = Lu + Lp; % free-energy - Ai = Lu + La; % free-action - % if F is increasing, save expansion point and derivatives + % free-energy and action %---------------------------------------------------------------------- - if Li > Fi || iN < 3 - - - Fi = Li; - F(iN) = Fi; - A(iN) = Ai; - - % save model-states (for each time point) - %================================================================== - for t = 1:length(qU) - v = spm_unvec(qU(t).v{1},v); - x = spm_unvec(qU(t).x{1},x); - z = spm_unvec(qE{t}(1:(ny + nv)),{M.v}); - w = spm_unvec(qE{t}([1:nx] + (ny + nv)*n),{M.x}); - for i = 1:(nl - 1) - if M(i).m, QU.v{i + 1}(:,t) = spm_vec(v{i}); end - if M(i).n, QU.x{i}(:,t) = spm_vec(x{i}); end - if M(i).n, QU.w{i}(:,t) = spm_vec(w{i}); end - if M(i).l, QU.z{i}(:,t) = spm_vec(z{i}); end - end - QU.v{1}(:,t) = spm_vec(qU(t).y{1}) - spm_vec(z{1}); - if M(nl).l, QU.z{nl}(:,t) = spm_vec(z{nl}); end - - % and conditional covariances - %-------------------------------------------------------------- - i = [1:nx]; - QU.S{t} = qU(t).c(i,i); - i = [1:nv] + nx*n; - QU.C{t} = qU(t).c(i,i); - end + Lu = - trace(iS(je,je)*EE(je,je))/2 ... % states (u) + - n*ny*log(2*pi)*nY/2 ... % constant + + spm_logdet(iS(je,je))*nY/2 ... % entropy - error + + iqu.c/(2*nD); % entropy q(u) + + Lp = - trace(qp.e'*pp.ic*qp.e)/2 ... % parameters (p) + - trace(qh.e'*ph.ic*qh.e)/2 ... % hyperparameters (h) + + spm_logdet(qp.c(ip,ip)*pp.ic)/2 ... % entropy q(p) + + spm_logdet(qh.c*ph.ic)/2; % entropy q(h) + + La = - trace(qp.e'*pp.ic*qp.e)*nY/2 ... % parameters (p) + - trace(qh.e'*ph.ic*qh.e)*nY/2 ... % hyperparameters (h) + + spm_logdet(qp.c(ip,ip)*pp.ic*nY)*nY/2 ... % entropy q(p) + + spm_logdet(qh.c*ph.ic*nY)*nY/2; % entropy q(h) + + Li = Lu + Lp; % free-energy + Ai = Lu + La; % free-action + + + % if F is increasing, save expansion point and derivatives + %------------------------------------------------------------------ + if Li > Fi || iE < 2 + - % save condotional densities + % Accept free-energy and save current parameter estimates %------------------------------------------------------------------ - B.QU = QU; - B.qp = qp; - B.qh = qh; - - % report and break if convergence + Fi = Li; + te = min(te + 1/2,4); + tm = min(tm + 1/2,4); + B.qp = qp; + B.qh = qh; + B.pp = pp; + + % E-step: update expectation (p) + %================================================================== + + % gradients and curvatures %------------------------------------------------------------------ - figure(Fdem) - spm_DEM_qU(QU) - if np - subplot(2*nl,2,4*nl) - bar(full(Up*qp.e)) - xlabel({'parameters {minus prior}'}) - end - if nh - subplot(2*nl,4,8*nl - 4) - bar(full(qh.h)) - title({'log-precision'}) - end - if length(F) > 2 - subplot(2*nl,4,8*nl - 5) - plot(F - F(1)) - xlabel('updates') - title('free-energy') - end - drawnow - - % report (EM-Steps) + dFdp(ip) = dFdp(ip) - pp.ic*(qp.e - pp.p); + dFdpp(ip,ip) = dFdpp(ip,ip) - pp.ic; + + % update conditional expectation %------------------------------------------------------------------ - str{1} = sprintf('DEM: %i (%i:%i:%i)',iN,iD,iE,iM); - str{2} = sprintf('F:%.4e',full(F(iN) - F(1))); - str{3} = sprintf('p:%.2e',full(mp'*mp)); - str{4} = sprintf('h:%.2e',full(mh'*mh)); - str{5} = sprintf('(%.2e sec)',full(toc)); - fprintf('%-16s%-16s%-14s%-14s%-16s\n',str{:}) - + dp = spm_dx(dFdpp,dFdp,{te}); + qp.e = qp.e + dp(ip); + qp.p = spm_unvec(qp.e,qp.p); + qp.b = spm_unvec(dp(ib),qp.b); + else - - % otherwise, return to previous expansion point and break + + % otherwise, return to previous expansion point %------------------------------------------------------------------ - QU = B.QU; - qp = B.qp; - qh = B.qh; - break + nM = 1; + qp = B.qp; + pp = B.pp; + qh = B.qh; + te = min(te - 2, -2); + tm = min(tm - 2, -2); end + F(iE) = Fi; + A(iE) = Ai; + + + % save model-states (for each time point) + %================================================================== + for t = 1:length(qU) + v = spm_unvec(qU(t).v{1},v); + x = spm_unvec(qU(t).x{1},x); + z = spm_unvec(qE{t}(1:(ny + nv)),{M.v}); + w = spm_unvec(qE{t}([1:nx] + (ny + nv)*n),{M.x}); + for i = 1:(nl - 1) + if M(i).m, QU.v{i + 1}(:,t) = spm_vec(v{i}); end + if M(i).n, QU.x{i}(:,t) = spm_vec(x{i}); end + if M(i).n, QU.w{i}(:,t) = spm_vec(w{i}); end + if M(i).l, QU.z{i}(:,t) = spm_vec(z{i}); end + end + QU.v{1}(:,t) = spm_vec(qU(t).y{1}) - spm_vec(z{1}); + if M(nl).l, QU.z{nl}(:,t) = spm_vec(z{nl}); end + + % and conditional covariances + %-------------------------------------------------------------- + i = (1:nx); + QU.S{t} = qU(t).c(i,i); + i = (1:nv) + nx*n; + QU.C{t} = qU(t).c(i,i); + end + + % report and break if convergence + %------------------------------------------------------------------ + figure(Fdem) + spm_DEM_qU(QU) + if np + subplot(2*nl,2,4*nl) + bar(full(Up*qp.e)) + xlabel({'parameters {minus prior}'}) + end + if nh + subplot(2*nl,4,8*nl - 4) + bar(full(qh.h)) + title({'log-precision'}) + end + if length(F) > 2 + subplot(2*nl,4,8*nl - 5) + plot(F - F(1)) + xlabel('updates') + title('free-energy') + end + drawnow + + % report (EM-Steps) + %------------------------------------------------------------------ + str{1} = sprintf('DEM: %i (%i:%i)',iE,iD,iM); + str{2} = sprintf('F:%.4e',full(F(iE) - F(1))); + str{3} = sprintf('p:%.2e',full(norm(dp,1))); + str{4} = sprintf('h:%.2e',full(norm(mh,1))); + str{5} = sprintf('(%.2e sec)',full(toc)); + fprintf('%-16s%-16s%-14s%-14s%-16s\n',str{:}) + + + % Convergence + %------------------------------------------------------------------ + if (norm(dp,1) < TOL*norm(spm_vec(qp.p),1)) && (norm(mh,1) < TOL), break, end + if te < -8, break, end + end % Assemble output arguments @@ -757,9 +722,11 @@ % conditional moments of model-parameters (rotated into original space) %-------------------------------------------------------------------------- -qP.P = spm_unvec(Up*qp.e + spm_vec(M.pE),M.pE); -qP.C = Up*qp.c(ip,ip)*Up'; -qP.V = spm_unvec(diag(qP.C),M.pE); +qP.P = spm_unvec(Up*qp.e + spm_vec(M.pE),M.pE); +qP.C = Up*qp.c(ip,ip)*Up'; +qP.V = spm_unvec(diag(qP.C),M.pE); +qP.dFdp = Up*dFdp(ip); +qP.dFdpp = Up*dFdpp(ip,ip)*Up'; % conditional moments of hyper-parameters (log-transformed) %-------------------------------------------------------------------------- diff --git a/spm_DEM_F.m b/spm_DEM_F.m new file mode 100644 index 0000000..f3a4c9a --- /dev/null +++ b/spm_DEM_F.m @@ -0,0 +1,70 @@ +function [F,p] = spm_DEM_F(DEM,ip) +% Free-energy as a function of conditional parameters +% [F,P1,P2] = spm_DEM_F(DEM)) +% +% DEM - hierarchical model +% +% F(i) - free-energy at = p(i) +% +% where p(i) is the ip-th free-parameter. This is a bound on +% the log-likehood (log-evidence) conditioned on the expeceted parameters +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_DEM_F.m 4146 2010-12-23 21:01:39Z karl $ + + +% Find paramter ranges (using prior covariance) +%-------------------------------------------------------------------------- +pE = spm_vec(DEM.M(1).pE); +p = linspace(-6,6,16); +dp = sqrt(DEM.M(1).pC(ip,ip))*p; +p = dp + pE(ip); + +% get F +%========================================================================== +DEM.M(1).E.nE = 1; +DEM.M(1).E.nN = 1; + +for i = 1:length(p) + + % adjust paramter (through prio expecatation) + %---------------------------------------------------------------------- + P = pE; + P(ip) = p(i); + DEM.M(1).P = spm_unvec(P,DEM.M(1).pE); + + % comute free-energy + %---------------------------------------------------------------------- + DEM = spm_DEM(DEM); + F(i) = DEM.F(end); + +end + + +% predicted F under the Laplace assumption +%========================================================================== +DEM.M(1).P = DEM.M(1).pE; +DEM = spm_DEM(DEM); + +% compute free-energy +%-------------------------------------------------------------------------- +dFdp = DEM.qP.dFdp(ip); +dFdpp = DEM.qP.dFdpp(ip,ip); +FP = dFdp*dp + (dFdpp*dp.^2)/2; +FP = FP - max(FP); + + +% plot +%-------------------------------------------------------------------------- +spm_figure('GetWin','Free-energy'); +F = F - max(F); +subplot(2,1,1) +plot(p,F,p,FP,':'), hold on +plot(pE(ip)*[1 1],[min(F) 0],':'), hold on +xlabel('Parameter expecatation','FontSize',12) +ylabel('Free-energy','FontSize',12) +title('Free-energy profile','FontSize',16) +axis square, box off + diff --git a/spm_DEM_M_set.m b/spm_DEM_M_set.m index 19d4942..6445975 100644 --- a/spm_DEM_M_set.m +++ b/spm_DEM_M_set.m @@ -48,7 +48,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_M_set.m 3733 2010-02-18 17:43:18Z karl $ +% $Id: spm_DEM_M_set.m 4146 2010-12-23 21:01:39Z karl $ % order %-------------------------------------------------------------------------- @@ -61,7 +61,6 @@ %-------------------------------------------------------------------------- if isfield(M,'f') && ~isfield(M,'n') && ~isfield(M,'x') msgbox('please specify hidden states or their number') - error(' ') end @@ -151,7 +150,6 @@ %---------------------------------------------------------------------- if length(M(i).pC) ~= np warndlg(sprintf('please check: M(%i).pC',i)) - who,keyboard end end @@ -199,12 +197,10 @@ f = feval(M(i).f,x,v,M(i).pE); if length(spm_vec(x)) ~= length(spm_vec(f)) warndlg(sprintf('please check: M(%i).f(x,v,P)',i)); - who,keyboard end catch warndlg(sprintf('evaluation failure: M(%i).f(x,v,P)',i)) - who,keyboard end try M(i).fx = fcnchk(M(i).fx,'x','v','P'); end try M(i).fv = fcnchk(M(i).fv,'x','v','P'); end @@ -227,7 +223,6 @@ catch warndlg(sprintf('evaluation failure: M(%i).g(x,v,P)',i)) - who,keyboard end try M(i).gx = fcnchk(M(i).gx,'x','v','P'); end try M(i).gv = fcnchk(M(i).gv,'x','v','P'); end @@ -249,7 +244,6 @@ M(i).xP = sparse(M(i).n,M(i).n); elseif any(size(M(i).xP) ~= [M(i).n M(i).n]); warndlg(sprintf('please Check: M(%i).xP',i)) - who,keyboard end end @@ -271,6 +265,7 @@ % check hyperpriors hE - [log]hyper-parameters and components %-------------------------------------------------------------------------- +pP = 1; % prior precision on log-precisions for i = 1:g @@ -294,11 +289,11 @@ % check hyperpriors (covariances) %---------------------------------------------------------------------- - try, M(i).hC*M(i).hE; catch, M(i).hC = speye(length(M(i).hE)); end - try, M(i).gC*M(i).gE; catch, M(i).gC = speye(length(M(i).gE)); end + try, M(i).hC*M(i).hE; catch, M(i).hC = speye(length(M(i).hE))/pP; end + try, M(i).gC*M(i).gE; catch, M(i).gC = speye(length(M(i).gE))/pP; end - if isempty(M(i).hC), M(i).hC = speye(length(M(i).hE)); end - if isempty(M(i).gC), M(i).gC = speye(length(M(i).gE)); end + if isempty(M(i).hC), M(i).hC = speye(length(M(i).hE))/pP; end + if isempty(M(i).gC), M(i).gC = speye(length(M(i).gE))/pP; end % check Q and R (precision components) %====================================================================== @@ -332,7 +327,6 @@ for j = 1:length(M(i).Q) if length(M(i).Q{j}) ~= M(i).l warndlg(sprintf('wrong size; M(%d).Q{%d}',i,j)) - who,keyboard end end @@ -341,7 +335,6 @@ for j = 1:length(M(i).R) if length(M(i).R{j}) ~= M(i).n warndlg(sprintf('wrong size; M(%d).R{%d}',i,j)) - who,keyboard end end @@ -397,17 +390,17 @@ % embedding orders %-------------------------------------------------------------------------- -try M(1).E.d; catch, if nx, M(1).E.d = 2; else M(1).E.d = 0; end, end -try M(1).E.n; catch, if nx, M(1).E.n = 6; else M(1).E.n = 0; end, end +try M(1).E.d; catch, if nx, M(1).E.d = 2; else M(1).E.d = 0; end, end +try M(1).E.n; catch, if nx, M(1).E.n = 6; else M(1).E.n = 0; end, end M(1).E.d = min(M(1).E.d,M(1).E.n); % number of iterations %-------------------------------------------------------------------------- -try M(1).E.nD; catch, if nx, M(1).E.nD = 1; else M(1).E.nD = 8; end, end -try M(1).E.nE; catch, M(1).E.nE = 1; end -try M(1).E.nM; catch, M(1).E.nM = 8; end -try M(1).E.nN; catch, M(1).E.nN = 16; end +try M(1).E.nD; catch, if nx, M(1).E.nD = 1; else M(1).E.nD = 8; end, end +try M(1).E.nE; catch, M(1).E.nE = 8; end +try M(1).E.nM; catch, M(1).E.nM = 8; end +try M(1).E.nN; catch, M(1).E.nN = 8; end % checks on smoothness hyperparameter %========================================================================== diff --git a/spm_DEM_R.m b/spm_DEM_R.m index 4b3a7ef..173a89d 100644 --- a/spm_DEM_R.m +++ b/spm_DEM_R.m @@ -1,6 +1,6 @@ -function [R,V,D] = spm_DEM_R(n,s,form) +function [R,V] = spm_DEM_R(n,s,form) % returns the precision of the temporal derivatives of a Gaussian process -% FORMAT [R,V,D] = spm_DEM_R(n,s,form) +% FORMAT [R,V] = spm_DEM_R(n,s,form) %__________________________________________________________________________ % n - truncation order % s - temporal smoothness - s.d. of kernel {bins} @@ -14,12 +14,11 @@ % % R - (n x n) E*V*E: precision of n derivatives % V - (n x n) V: covariance of n derivatives -% D - (n x n) D: projector: Y(t) <- D*y[:] %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_R.m 3878 2010-05-07 19:53:54Z karl $ +% $Id: spm_DEM_R.m 4278 2011-03-31 11:48:00Z karl $ % if no serial dependencies %-------------------------------------------------------------------------- @@ -31,7 +30,7 @@ % temporal correlations (assuming known form) - V %-------------------------------------------------------------------------- -try, form;, catch, form = 'Gaussian'; end +try, form; catch, form = 'Gaussian'; end switch form @@ -97,7 +96,7 @@ % NB: temporal correlations (assuming stationary Gaussian form) %-------------------------------------------------------------------------- -t = ([1:n] - 1)*dt; +t = ((1:n) - 1)*dt; v = 2*(s^2); V = exp(-t.^2/(2*v)); V = toeplitz(V); diff --git a/spm_DEM_diff.m b/spm_DEM_diff.m index 2eab3b8..a6e4617 100644 --- a/spm_DEM_diff.m +++ b/spm_DEM_diff.m @@ -17,7 +17,7 @@ % Copyright (C) 2005 Wellcome Department of Imaging Neuroscience % Karl Friston -% $Id: spm_DEM_diff.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM_diff.m 4247 2011-03-14 18:16:50Z karl $ % Check for action (ADEM) %========================================================================== diff --git a/spm_DEM_qH.m b/spm_DEM_qH.m index e34e85b..7c7e7b0 100644 --- a/spm_DEM_qH.m +++ b/spm_DEM_qH.m @@ -15,14 +15,13 @@ function spm_DEM_qH(qH,pH) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_qH.m 3878 2010-05-07 19:53:54Z karl $ +% $Id: spm_DEM_qH.m 4052 2010-08-27 19:22:44Z karl $ % unpack conditional covariances %-------------------------------------------------------------------------- try, qH = qH.qH; end try, pH = pH.pH; end - % [Re]ML estimates - h %========================================================================== ci = spm_invNcdf(1 - 0.05); @@ -64,35 +63,39 @@ function spm_DEM_qH(qH,pH) h = spm_vec(qH.g); c = spm_vec(qH.W); c = sqrt(c)*spm_invNcdf(1 - 0.05); -subplot(2,2,2) -bar(full(h),'Edgecolor',[1 1 1]/2,'Facecolor',[1 1 1]*.8) -title({'log-precision';'states'},'FontSize',16); -axis square -set(gca,'XLim',[0 length(c) + 1]) - -% conditional covariances -%-------------------------------------------------------------------------- -for i = 1:length(c) - line([i i],[-1 1]*c(i) + h(i),'LineWidth',4,'Color','r'); -end - -% prior or true means -%-------------------------------------------------------------------------- -try - p = spm_vec(pH.g); - for i = 1:length(h) - line([-1 1]/2 + i,[0 0] + p(i),'LineWidth',4,'Color','k'); +if h + subplot(2,2,2) + bar(full(h),'Edgecolor',[1 1 1]/2,'Facecolor',[1 1 1]*.8) + title({'log-precision';'states'},'FontSize',16); + axis square + set(gca,'XLim',[0 length(c) + 1]) + + % conditional covariances + %---------------------------------------------------------------------- + for i = 1:length(c) + line([i i],[-1 1]*c(i) + h(i),'LineWidth',4,'Color','r'); end -end - -glabel = {}; -for i = 1:length(qH.h) - for j = 1:length(qH.h{i}) - glabel{end + 1} = sprintf('g:level %i',i); + + % prior or true means + %---------------------------------------------------------------------- + try + p = spm_vec(pH.g); + for i = 1:length(h) + line([-1 1]/2 + i,[0 0] + p(i),'LineWidth',4,'Color','k'); + end end + + glabel = {}; + for i = 1:length(qH.h) + for j = 1:length(qH.h{i}) + glabel{end + 1} = sprintf('g:level %i',i); + end + end + set(gca,'XTickLabel',glabel) +else + glabel = {}; end -set(gca,'XTickLabel',glabel) - + % conditional covariance and correlations %-------------------------------------------------------------------------- subplot(2,2,3) diff --git a/spm_DEM_qU.m b/spm_DEM_qU.m index 526d053..3ce9c4e 100644 --- a/spm_DEM_qU.m +++ b/spm_DEM_qU.m @@ -13,7 +13,7 @@ function spm_DEM_qU(qU,pU) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_qU.m 3878 2010-05-07 19:53:54Z karl $ +% $Id: spm_DEM_qU.m 4247 2011-03-14 18:16:50Z karl $ % unpack %-------------------------------------------------------------------------- @@ -31,17 +31,23 @@ function spm_DEM_qU(qU,pU) pV = pU.v; pX = pU.x; end + +% order of hierarchy +%-------------------------------------------------------------------------- try - pA = qU.a; + g = length(X) + 1; + if issempty(X{end}) + g = g - 1; + end +catch + g = length(V); end - + % time-series specification %-------------------------------------------------------------------------- -g = length(V); % order of hierarchy -N = size(V{1},2); % length of data sequence -dt = 1; % time step -t = [1:N]*dt; % time - +N = size(V{1},2); % length of data sequence +dt = 1; % time step +t = [1:N]*dt; % time % unpack conditional covariances %-------------------------------------------------------------------------- @@ -61,7 +67,7 @@ function spm_DEM_qU(qU,pU) if N == 1 - % causal states and error - single observation + % hidden causes and error - single observation %------------------------------------------------------------------ subplot(g,2,2*i - 1) t = 1:size(V{i},1); @@ -77,7 +83,7 @@ function spm_DEM_qU(qU,pU) y = ci*c(j,:); c(j,:) = []; fill([t fliplr(t)],[full(V{i} + y)' fliplr(full(V{i} - y)')],... - [1 1 1]*.8,'EdgeColor',[1 1 1]*.6) + [1 1 1]*.8,'EdgeColor',[1 1 1]*.8) plot(t,full(E{i}),'r:',t,full(V{i})) hold off end @@ -91,17 +97,20 @@ function spm_DEM_qU(qU,pU) else - % causal states and error - time series + % hidden causes and error - time series %------------------------------------------------------------------ subplot(g,2,2*i - 1) try - plot(t,pV{i},':k','linewidth',1),box off + plot(t,pV{i},':k','linewidth',1) end hold on try - plot(t,full(E{i}(:,1:N)),'r:',t,full(V{i})),box off + plot(t,full(V{i})) end - hold off + try + plot(t,full(E{i}),'r:') + end + box off, hold off set(gca,'XLim',[t(1) t(end)]) a = axis; @@ -109,15 +118,18 @@ function spm_DEM_qU(qU,pU) %------------------------------------------------------------------ if i > 1 && size(c,1) hold on - j = [1:size(V{i},1)]; + j = (1:size(V{i},1)); y = ci*c(j,:); c(j,:) = []; fill([t fliplr(t)],[full(V{i} + y) fliplr(full(V{i} - y))],... - [1 1 1]*.8,'EdgeColor',[1 1 1]*.6) + [1 1 1]*.8,'EdgeColor',[1 1 1]*.8) try - plot(t,pV{i},':k','linewidth',1),box off + plot(t,pV{i},':k','linewidth',1) + end + try + plot(t,full(E{i}),'r:') end - plot(t,full(E{i}(:,1:N)),'r:',t,full(V{i})) + plot(t,full(V{i})),box off hold off end @@ -125,6 +137,8 @@ function spm_DEM_qU(qU,pU) %------------------------------------------------------------------ if i == 1 title('prediction and error','FontSize',16); + elseif length(V) < i + title('no causes','FontSize',16); elseif ~size(V{i},1) title('no causes','FontSize',16); else @@ -134,11 +148,6 @@ function spm_DEM_qU(qU,pU) plot(t,pV{i},':k','linewidth',1),box off end hold off - try - hold on - plot(t,pA{i - 1},'linewidth',1,'color',[1 0 0]),box off - end - hold off end xlabel('time','FontSize',14) axis square @@ -189,14 +198,16 @@ function spm_DEM_qU(qU,pU) %-------------------------------------------------------------------------- if isfield(qU,'a') subplot(g,2,2*g) - plot(t,qU.a{2}); + plot(t,qU.a{end}); + str = 'action'; try hold on plot(t,pU.v{2},':b','Linewidth',2),box off + str = 'perturbation and action'; end hold off xlabel('time','Fontsize',14) - title('perturbation and action','Fontsize',16) + title(str,'Fontsize',16) axis square set(gca,'XLim',[t(1) t(end)]) box off diff --git a/spm_DesMtx.m b/spm_DesMtx.m index d224f79..1e15ab1 100644 --- a/spm_DesMtx.m +++ b/spm_DesMtx.m @@ -1,4 +1,4 @@ -function [X,Pnames,Index,idx,jdx,kdx]=spm_DesMtx(varargin); +function [X,Pnames,Index,idx,jdx,kdx]=spm_DesMtx(varargin) % Design matrix construction from factor level and covariate vectors % FORMAT [X,Pnames] = spm_DesMtx( list) % FORMAT [X,Pnames,Index,idx,jdx,kdx] = spm_DesMtx(FCLevels,Constraint,FCnames) @@ -250,7 +250,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_DesMtx.m 3934 2010-06-17 14:58:25Z guillaume $ +% $Id: spm_DesMtx.m 4137 2010-12-15 17:18:32Z guillaume $ @@ -261,12 +261,12 @@ if ischar(varargin{1}) %-Non-recursive action string usage Constraint=varargin{1}; -elseif nargin>=2 & ~(ischar(varargin{2}) | iscell(varargin{2})) +elseif nargin>=2 && ~(ischar(varargin{2}) || iscell(varargin{2})) [X1,Pnames1]=spm_DesMtx(varargin{1}); [X2,Pnames2]=spm_DesMtx(varargin{2:end}); X=[X1,X2]; Pnames=[Pnames1;Pnames2]; return -elseif nargin>=3 & ~(ischar(varargin{3}) | iscell(varargin{3})) +elseif nargin>=3 && ~(ischar(varargin{3}) || iscell(varargin{3})) [X1,Pnames1]=spm_DesMtx(varargin{1:2}); [X2,Pnames2]=spm_DesMtx(varargin{3:end}); X=[X1,X2]; Pnames=[Pnames1;Pnames2]; @@ -280,9 +280,9 @@ %-If I is a vector, make it a column vector I=varargin{1}; if size(I,1)==1, I=I'; end %-Sort out constraint and Factor/Covariate name parameters - if nargin<2, Constraint='-'; else, Constraint=varargin{2}; end + if nargin<2, Constraint='-'; else Constraint=varargin{2}; end if isempty(I), Constraint='mt'; end - if nargin<3, FCnames={}; else, FCnames=varargin{3}; end + if nargin<3, FCnames={}; else FCnames=varargin{3}; end if char(FCnames), FCnames=cellstr(FCnames); end end @@ -304,10 +304,10 @@ %-Construct parameter name index %----------------------------------------------------------------------- if isempty(FCnames) - if strcmp(Constraint,'C'), FCnames={''}; else, FCnames={''}; end + if strcmp(Constraint,'C'), FCnames={''}; else FCnames={''}; end end -if length(FCnames)==1 & size(X,2)>1 +if length(FCnames)==1 && size(X,2)>1 Pnames = cell(size(X,2),1); for i=1:size(X,2) Pnames{i} = sprintf('%s [%d]',FCnames{1},i); @@ -443,7 +443,7 @@ %-Set up design matrix X & names matrix - ignore zero levels if '~FxC' use %----------------------------------------------------------------------- if Constraint(1)~='~', [X,Pnames,Index] = spm_DesMtx(F,'-',Fnames); - else, [X,Pnames,Index] = spm_DesMtx(F,'~',Fnames); end + else [X,Pnames,Index] = spm_DesMtx(F,'~',Fnames); end X = X.*(C*ones(1,size(X,2))); Pnames = cellstr([repmat([Cnames,'@'],size(Index,2),1),char(Pnames)]); @@ -463,7 +463,7 @@ %-'.0' corner point constraint is applied to zero factor level only nXcols = size(X,2); zCol = find(Index==0); -if nXcols==1 & ~strcmp(Constraint,'.0') +if nXcols==1 && ~strcmp(Constraint,'.0') error('only one level: can''t constrain') elseif strcmp(Constraint,'.') X(:,nXcols)=[]; Pnames(nXcols)=[]; Index(nXcols)=[]; @@ -572,7 +572,7 @@ if CornerPointI %-impose CornerPointI constraints if Constraint(end)~='0', i = max(Index(1,:)); - else, i = 0; end + else i = 0; end cols=find(Index(1,:)==i); %-columns to delete if isempty(cols) warning('no zero i level to constrain') @@ -585,7 +585,7 @@ if CornerPointJ %-impose CornerPointJ constraints if Constraint(end)~='0', j = max(Index(2,:)); - else, j = 0; end + else j = 0; end cols=find(Index(2,:)==j); if isempty(cols) warning('no zero j level to constrain') @@ -600,9 +600,9 @@ case {'PDS','pds'} %-Patterned data set utility %======================================================================= % i = spm_DesMtx('pds',v,m,n) -if nargin<4, n=1; else, n=varargin{4}; end -if nargin<3, m=1; else, m=varargin{3}; end -if nargin<2, varargout={[]}, return, else, v=varargin{2}; end +if nargin<4, n=1; else n=varargin{4}; end +if nargin<3, m=1; else m=varargin{3}; end +if nargin<2, varargout={[]}; return, else v=varargin{2}; end if any([size(n),size(m)])>1, error('n & m must be scalars'), end if any(([m,n]~=floor([m,n]))|([m,n]<1)) error('n & m must be natural numbers'), end @@ -623,8 +623,8 @@ %----------------------------------------------------------------------- while(Carg <= nargin) rX = varargin{Carg}; Carg=Carg+1; - if Carg<=nargin & ~isempty(varargin{Carg}) & ... - (ischar(varargin{Carg}) | iscellstr(varargin{Carg})) + if Carg<=nargin && ~isempty(varargin{Carg}) && ... + (ischar(varargin{Carg}) || iscellstr(varargin{Carg})) rPnames = char(varargin{Carg}); Carg=Carg+1; else %-No names to work out blocks from - normalise by column rPnames = repmat('',size(rX,2),1); @@ -634,7 +634,7 @@ while(~isempty(rX)) - if size(rX,2)>1 & max([1,find(rPnames(1,:)=='(')]) < ... + if size(rX,2)>1 && max([1,find(rPnames(1,:)=='(')]) < ... max([0,find(rPnames(1,:)==')')]) %-Non-specific block: find the rest & column normalise round zero %=============================================================== @@ -658,7 +658,7 @@ rX(:,1:t) = []; rPnames(1:t,:)=[]; - elseif size(rX,2)>1 & max([1,find(rPnames(1,:)=='[')]) < ... + elseif size(rX,2)>1 && max([1,find(rPnames(1,:)=='[')]) < ... max([0,find(rPnames(1,:)==']')]) %-Block: find the rest & normalise together %=============================================================== @@ -674,7 +674,7 @@ rX(:,1:t) = []; rPnames(1:t,:)=[]; - elseif size(rX,2)>1 & max([1,strfind(rPnames(1,:),'_{')]) < ... + elseif size(rX,2)>1 && max([1,strfind(rPnames(1,:),'_{')]) < ... max([0,find(rPnames(1,:)=='}')]) %-Factor, interaction of factors, or FxC: find the rest... %=============================================================== @@ -754,9 +754,9 @@ '\rho', 'covint';... '\zeta', 'global';... '\epsilon', 'error'}; -if nargin<2, aMap={}; else, aMap = varargin{2}; end +if nargin<2, aMap={}; else aMap = varargin{2}; end if isempty(aMap), X=Map; return, end -if ~(iscellstr(aMap) & ndims(aMap)==2), error('aMap must be an nx2 cellstr'), end +if ~(iscellstr(aMap) && ndims(aMap)==2), error('aMap must be an nx2 cellstr'), end for i=1:size(aMap,1) j = find(strcmp(aMap{i,1},Map(:,1))); if isempty(j) @@ -772,7 +772,7 @@ %======================================================================= % EPnames = spm_DesMtx('TeXnames',Pnames,aMap) if nargin<2, varargout={''}; return, end -if nargin<3, aMap={}; else, aMap = varargin{3}; end +if nargin<3, aMap={}; else aMap = varargin{3}; end Map = spm_DesMtx('ParMap',aMap); EPnames = varargin{2}; for i=1:size(Map,1) diff --git a/spm_DesRep.m b/spm_DesRep.m index 43a230f..c618ec0 100644 --- a/spm_DesRep.m +++ b/spm_DesRep.m @@ -128,7 +128,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_DesRep.m 1157 2008-02-19 11:34:58Z guillaume $ +% $Id: spm_DesRep.m 4209 2011-02-22 20:11:05Z guillaume $ @@ -262,7 +262,13 @@ %-Format arguments %----------------------------------------------------------------------- -if nargin==0, spm_DesRep('DesRepUI'); return, end +if nargin==0 + hC = spm_DesRep('DesRepUI'); + SPM = get(hC,'UserData'); + spm_DesRep('DesMtx',SPM.xX,... + reshape({SPM.xY.VY.fname},size(SPM.xY.VY)),SPM.xsDes); + return; +end switch lower(varargin{1}) @@ -293,10 +299,10 @@ %======================================================================= %-Work out where design configuration has come from! if ~isfield(SPM,'cfg') - if isfield(SPM.xX,'V'), cfg = 'SPMest'; - elseif isfield(SPM.xY,'VY'), cfg = 'SPMdata'; - elseif isfield(SPM,'Sess'), cfg = 'SPMcfg'; - else, error('Can''t fathom origin!') + if isfield(SPM.xX,'V'), cfg = 'SPMest'; + elseif isfield(SPM.xY,'VY'), cfg = 'SPMdata'; + elseif isfield(SPM,'Sess'), cfg = 'SPMcfg'; + else error('Can''t fathom origin!') end SPM.cfg = cfg; end @@ -397,8 +403,10 @@ hxvi = uimenu(hExplore, 'Label','Covariance structure', ... 'Callback',[cb, 'spm_DesRep(''xVi'', tmp.xVi);'], 'UserData',hC, 'HandleVisibility','off'); -if ~isfield(SPM,'xVi') | (isfield(SPM.xVi,'iid') & SPM.xVi.iid) | ... - ~(isfield(SPM.xVi,'V')|isfield(SPM.xVi,'Vi')), set(hxvi,'Enable','off'); end; +if ~isfield(SPM,'xVi') || (isfield(SPM.xVi,'iid') && SPM.xVi.iid) || ... + ~(isfield(SPM.xVi,'V') || isfield(SPM.xVi,'Vi')) + set(hxvi,'Enable','off'); +end %-Clear, Quit, Help %----------------------------------------------------------------------- @@ -427,7 +435,7 @@ I = varargin{3}; xC = varargin{4}; sF = varargin{5}; -if nargin<6, xs=[]; else, xs = varargin{6}; end %-Structure of strings +if nargin<6, xs=[]; else xs = varargin{6}; end %-Structure of strings [fnames,CPath] = spm_str_manip(fnames,'c'); %-extract common path component nScan = size(I,1); %-#images @@ -460,7 +468,7 @@ for j = 1:length(xC) n = size(xC(j).rc,2); - if n>1, tmp=xC(j).cname; else, tmp={xC(j).rcname}; end + if n>1, tmp=xC(j).cname; else tmp={xC(j).rcname}; end for k=1:n x=x+dx2; text(x,.1,tmp{k},'Rotation',90,'Interpreter','TeX') @@ -532,9 +540,9 @@ text(0.3,y,[strrep(sf{1},'_',' '),' :'],... 'HorizontalAlignment','Right','FontWeight','Bold',... 'FontSize',FS(9)) - s = getfield(xs,sf{1}); + s = xs.(sf{1}); if ~iscellstr(s), s={s}; end - for i=1:prod(size(s)) + for i=1:numel(s) text(0.31,y,s{i},'FontSize',FS(9)) y=y-dy; end @@ -601,23 +609,23 @@ str = sprintf('Covariance structure V: %s',varargin{2}.form); else str = 'Covariance structure V'; - end; - if isfield(varargin{2},'var') & isfield(varargin{2},'dep') & ... - isfield(varargin{2},'sF') & isfield(varargin{2},'I') + end + if isfield(varargin{2},'var') && isfield(varargin{2},'dep') && ... + isfield(varargin{2},'sF') && isfield(varargin{2},'I') r = find((max(varargin{2}.I) > 1) & ~varargin{2}.var & ~varargin{2}.dep); if any(varargin{2}.dep) cmstr = 'yes'; else cmstr = 'no'; - end; + end str = sprintf(['Covariance structure V - replications over ''%s''\n'... 'Correlated repeated measures: %s'], ... varargin{2}.sF{r},cmstr); - end; + end xlabel(str); else text(.5,.5, 'Covariance not (yet) estimated.', 'HorizontalAlignment','center'); -end; +end if isfield(varargin{2},'h') hPEstAx = axes('Position',[.07 .315 .6 .025],... @@ -660,30 +668,30 @@ % spm_DesRep('DesOrth',xX) if nargin<2, error('insufficient arguments'), end if ~isstruct(varargin{2}), error('design matrix structure required'), end -if nargin<3, fnames={}; else, fnames=varargin{3}; end -if nargin<4, xs=[]; else, xs=varargin{4}; end +if nargin<3, fnames={}; else fnames=varargin{3}; end +if nargin<4, xs=[]; else xs=varargin{4}; end -desmtx = strcmp(lower(varargin{1}),'desmtx'); +desmtx = strcmpi(varargin{1},'desmtx'); %-Locate DesMtx (X), scaled DesMtx (nX) & get parameter names (Xnames) %----------------------------------------------------------------------- -if isfield(varargin{2},'xKXs') & ... - ~isempty(varargin{2}.xKXs) & isstruct(varargin{2}.xKXs) +if isfield(varargin{2},'xKXs') && ... + ~isempty(varargin{2}.xKXs) && isstruct(varargin{2}.xKXs) iX = 1; [nScan,nPar] = size(varargin{2}.xKXs.X); -elseif isfield(varargin{2},'X') & ~isempty(varargin{2}.X) +elseif isfield(varargin{2},'X') && ~isempty(varargin{2}.X) iX = 0; [nScan,nPar] = size(varargin{2}.X); else error('Can''t find DesMtx in this structure!') end -if isfield(varargin{2},'nKX') & ~isempty(varargin{2}.nKX) - inX = 1; else, inX = 0; end +if isfield(varargin{2},'nKX') && ~isempty(varargin{2}.nKX) + inX = 1; else inX = 0; end -if isfield(varargin{2},'name') & ~isempty(varargin{2}.name) - Xnames = varargin{2}.name; else, Xnames = {}; end +if isfield(varargin{2},'name') && ~isempty(varargin{2}.name) + Xnames = varargin{2}.name; else Xnames = {}; end %-Compute design orthogonality matrix if DesOrth @@ -767,7 +775,7 @@ %-Filenames % ( Show at most 32, showing every 2nd/3rd/4th/... as necessary to pair ) % ( down to <32 items. Always show last item so #images is indicated. ) -if desmtx & ~isempty(fnames) +if desmtx && ~isempty(fnames) axes('Position',[.68 .4 .3 .4],'Visible','off',... 'DefaultTextFontSize',FS(8),... 'YLim',[0,nScan]+0.5,'YDir','Reverse') @@ -785,7 +793,7 @@ %----------------------------------------------------------------------- if iX, set(hDesMtxIm,'UserData',... struct('X',varargin{2}.xKXs.X,'Xnames',{Xnames},'fnames',{fnames})) -else, set(hDesMtxIm,'UserData',... +else set(hDesMtxIm,'UserData',... struct('X',varargin{2}.X, 'Xnames',{Xnames},'fnames',{fnames})) end set(hDesMtxIm,'ButtonDownFcn','spm_DesRep(''SurfDesMtx_CB'')') @@ -797,7 +805,7 @@ hPEstAx = axes('Position',[.07 .315 .6 .025],... 'DefaultTextInterpreter','TeX'); if iX, est = spm_SpUtil('IsCon',varargin{2}.xKXs); - else, est = spm_SpUtil('IsCon',varargin{2}.X); end + else est = spm_SpUtil('IsCon',varargin{2}.X); end hParEstIm = image((est+1)*32); set(hPEstAx,... 'XLim',[0,nPar]+.5,'XTick',[1:nPar-1]+.5,'XTickLabel','',... @@ -879,9 +887,9 @@ text(0.3,y,[strrep(sf{1},'_',' '),' :'],... 'HorizontalAlignment','Right','FontWeight','Bold',... 'FontSize',FS(9)) - s = getfield(xs,sf{1}); + s = xs.(sf{1}); if ~iscellstr(s), s={s}; end - for i=1:prod(size(s)) + for i=1:numel(s) text(0.31,y,s{i},'FontSize',FS(9)) y=y-dy; end @@ -901,7 +909,7 @@ xC = varargin{3}; %-Struct array of covariate information if ~isstruct(varargin{2}), error('design matrix structure required'), end -if ~length(xC), spm('alert!','No covariates!',mfilename), return, end +if isempty(xC), spm('alert!','No covariates!',mfilename), return, end %-Get graphics window & window scaling Fgraph = spm_figure('GetWin','Graphics'); @@ -929,14 +937,14 @@ %-Design matrix (as underlay for plots) and parameter names %----------------------------------------------------------------------- [nScan,nPar] = size(varargin{2}.X); -if isfield(varargin{2},'name') & ~isempty(varargin{2}.name) - Xnames = varargin{2}.name; else, Xnames = {}; end +if isfield(varargin{2},'name') && ~isempty(varargin{2}.name) + Xnames = varargin{2}.name; else Xnames = {}; end %-Design matrix hDesMtx = axes('Position',[.1 .5 .7 .3]); -if isfield(varargin{2},'nKX') & ~isempty(varargin{2}.nKX) +if isfield(varargin{2},'nKX') && ~isempty(varargin{2}.nKX) image(varargin{2}.nKX'*32+32) -elseif isfield(varargin{2},'xKXs') & ~isempty(varargin{2}.xKXs) +elseif isfield(varargin{2},'xKXs') && ~isempty(varargin{2}.xKXs) image(spm_DesMtx('sca',varargin{2}.xKXs.X,Xnames)*32+32) else image(spm_DesMtx('sca',varargin{2}.X,Xnames)*32+32) @@ -990,7 +998,7 @@ 'FontWeight','Bold','FontSize',FS(9)) s = xC(i).descrip; if ~iscellstr(s), s={s}; end - for j=1:prod(size(s)) + for j=1:numel(s) text(0.31,y,s{j},'FontSize',FS(9)) y=y-dy; end @@ -1067,7 +1075,7 @@ % spm_DesRep('ScanTick',nScan,lim) % ( Show at most 32, showing every 2nd/3rd/4th/... as necessary to pair ) % ( down to <32 items. Always show last item so #images is indicated. ) -if nargin<3, lim=32; else, lim=varargin{3}; end +if nargin<3, lim=32; else lim=varargin{3}; end if nargin<2, error('insufficient arguments'), end nScan = varargin{2}; @@ -1086,7 +1094,7 @@ h = get(gca,'Xlabel'); -if strcmp(lower(varargin{1}),'surfdesmtxup_cb') +if strcmpi(varargin{1},'surfdesmtxup_cb') UD = get(h,'UserData'); set(h,'String',UD.String,'Interpreter',UD.Interpreter,... 'UserData',UD.UserData) @@ -1095,13 +1103,13 @@ end -if strcmp(lower(varargin{1}),'surfdesmtx_cb') - UD = struct( 'String', get(h,'String'),... - 'Interpreter', get(h,'Interpreter'),... - 'UserData', get(h,'UserData')); +if strcmpi(varargin{1},'surfdesmtx_cb') + UD = struct('String', get(h,'String'),... + 'Interpreter', get(h,'Interpreter'),... + 'UserData', get(h,'UserData')); set(h,'UserData',UD) set(gcbf,'WindowButtonMotionFcn','spm_DesRep(''SurfDesMtxMo_CB'')',... - 'WindowButtonUpFcn', 'spm_DesRep(''SurfDesMtxUp_CB'')') + 'WindowButtonUpFcn','spm_DesRep(''SurfDesMtxUp_CB'')') end mm = [get(gca,'YLim')',get(gca,'XLim')']+[.5,.5;-.5,-.5]; @@ -1149,7 +1157,7 @@ h = get(gca,'Xlabel'); -if strcmp(lower(varargin{1}),'surfestimup_cb') +if strcmpi(varargin{1},'surfestimup_cb') UD = get(h,'UserData'); set(h,'String',UD.String,'Interpreter',UD.Interpreter,... 'UserData',UD.UserData) @@ -1157,7 +1165,7 @@ return end -if strcmp(lower(varargin{1}),'surfestim_cb') +if strcmpi(varargin{1},'surfestim_cb') UD = struct( 'String', get(h,'String'),... 'Interpreter', get(h,'Interpreter'),... 'UserData', get(h,'UserData')); @@ -1208,7 +1216,7 @@ h = get(gca,'Xlabel'); -if strcmp(lower(varargin{1}),'surfdesoup_cb') +if strcmpi(varargin{1},'surfdesoup_cb') UD = get(h,'UserData'); set(h,'String',UD.String,'Interpreter',UD.Interpreter,... 'UserData',UD.UserData) @@ -1216,7 +1224,7 @@ return end -if strcmp(lower(varargin{1}),'surfdeso_cb') +if strcmpi(varargin{1},'surfdeso_cb') UD = struct( 'String', get(h,'String'),... 'Interpreter', get(h,'Interpreter'),... 'UserData', get(h,'UserData')); @@ -1243,11 +1251,12 @@ str = '{\bf not orthogonal}'; end if ~diff(ij), str=[str,' {\it(same column)}']; end - if UD.bC(ij(1),ij(2)), tmp=' ={\it r}'; else, tmp=''; end - str = { sprintf('{\\bf %s} (col %d) & {\\bf %s} (col %d)',... - UD.name{ij(1)},ij(1),... - UD.name{ij(2)},ij(2)),... - sprintf('cos(\\theta)%s = %1.2f',... + if UD.bC(ij(1),ij(2)), tmp=' ={\it r}'; else tmp=''; end + str = { sprintf('{\\bf %s} (col %d)',... + UD.Xnames{ij(1)},ij(1)),... + sprintf('& {\\bf %s} (col %d)',... + UD.Xnames{ij(2)},ij(2)),... + sprintf('cos(\\theta)%s = %1.2f',... tmp,UD.O(ij(1),ij(2))),... ['\rightarrow ',str]}; istr = 'tex'; @@ -1274,12 +1283,12 @@ % spm_DesRep('SurfConOUp_CB') cUD = get(gco,'UserData'); -if ~isstruct(cUD) | ~isfield(cUD,'h') +if ~isstruct(cUD) || ~isfield(cUD,'h') warning('contrast GUI objects setup incorrectly'), return end h = cUD.h; -if strcmp(lower(varargin{1}),'surfconup_cb') +if strcmpi(varargin{1},'surfconup_cb') UD = get(h,'UserData'); set(h,'String',UD.String,'Interpreter',UD.Interpreter,... 'UserData',UD.UserData) @@ -1287,7 +1296,7 @@ return end -if strcmp(lower(varargin{1}),'surfcon_cb') +if strcmpi(varargin{1},'surfcon_cb') UD = struct( 'String', get(h,'String'),... 'Interpreter', get(h,'Interpreter'),... 'UserData', get(h,'UserData')); @@ -1304,7 +1313,7 @@ switch get(gcbf,'SelectionType') case 'normal' try - if cUD.i>0, str = sprintf('%d',cUD.i); else, str = ''; end + if cUD.i>0, str = sprintf('%d',cUD.i); else str = ''; end switch get(gco,'Type') case 'image' str = sprintf('%s\\{F\\}: {\\bf%s} (%d,%d) = %.2f',... @@ -1339,7 +1348,7 @@ h = get(gca,'Xlabel'); -if strcmp(lower(varargin{1}),'surfxviup_cb') +if strcmpi(varargin{1},'surfxviup_cb') UD = get(h,'UserData'); set(h,'String',UD.String,'Interpreter',UD.Interpreter,... 'UserData',UD.UserData) @@ -1348,7 +1357,7 @@ end -if strcmp(lower(varargin{1}),'surfxvi_cb') +if strcmpi(varargin{1},'surfxvi_cb') UD = struct( 'String', get(h,'String'),... 'Interpreter', get(h,'Interpreter'),... 'UserData', get(h,'UserData')); @@ -1366,8 +1375,8 @@ case 'normal' try str = sprintf('V(%d,%d) = %g',ij(1),ij(2),... - subsref(get(gco,'UserData'),... - struct('type',{'.','()'},'subs',{'V',{ij(1),ij(2)}}))); + full(subsref(get(gco,'UserData'),... + struct('type',{'.','()'},'subs',{'V',{ij(1),ij(2)}})))); catch str = '(no cached covariance matrix to surf)'; end @@ -1375,7 +1384,7 @@ try ind = 1:length(subsref(get(gco,'Userdata'),... struct('type','.','subs','h'))); - isel = logical(zeros(size(ind))); + isel = false(size(ind)); for k = 1:length(ind) isel(k) = subsref(get(gco,'UserData'),... struct('type',{'.','{}','()'},'subs',{'Vi',{k},{ij(1),ij(2)}})) ~= 0; @@ -1412,7 +1421,7 @@ h = get(gca,'Xlabel'); -if strcmp(lower(varargin{1}),'surfhpestimup_cb') +if strcmpi(varargin{1},'surfhpestimup_cb') UD = get(h,'UserData'); set(h,'String',UD.String,'Interpreter',UD.Interpreter,... 'UserData',UD.UserData) @@ -1420,7 +1429,7 @@ return end -if strcmp(lower(varargin{1}),'surfhpestim_cb') +if strcmpi(varargin{1},'surfhpestim_cb') UD = struct( 'String', get(h,'String'),... 'Interpreter', get(h,'Interpreter'),... 'UserData', get(h,'UserData')); diff --git a/spm_Dpdf.m b/spm_Dpdf.m index 2f455c0..91c2661 100644 --- a/spm_Dpdf.m +++ b/spm_Dpdf.m @@ -16,13 +16,13 @@ % % Algorithm: %-------------------------------------------------------------------------- -% Direct computation using logs and Matlab's implementation of the log of +% Direct computation using logs and MATLAB's implementation of the log of % the gamma function (gammaln). %__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% Copyright (C) 2008-2011 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_Dpdf.m 2636 2009-01-21 09:57:20Z guillaume $ +% $Id: spm_Dpdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Check enough arguments %-------------------------------------------------------------------------- diff --git a/spm_FcUtil.m b/spm_FcUtil.m index 7d665de..d49c36d 100644 --- a/spm_FcUtil.m +++ b/spm_FcUtil.m @@ -127,13 +127,13 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jean-Baptiste Poline -% $Id: spm_FcUtil.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_FcUtil.m 4137 2010-12-15 17:18:32Z guillaume $ %-Format arguments %----------------------------------------------------------------------- if nargin==0, error('do what? no arguments given...') -else, action = varargin{1}; end +else action = varargin{1}; end switch lower(action), @@ -142,10 +142,10 @@ %======================================================================= % Fc = spm_FcUtil('FconFields') -if nargout > 1, error('Too many output arguments: FconFields'), end; -if nargin > 1, error('Too many input arguments: FconFields'), end; +if nargout > 1, error('Too many output arguments: FconFields'), end +if nargin > 1, error('Too many input arguments: FconFields'), end -varargout = {sf_FconFields;} +varargout = {sf_FconFields}; case {'set','v1set'} %- Create an F contrast %======================================================================= @@ -167,20 +167,20 @@ %-check # arguments... %-------------------------------------------------------------------------- -if nargin<6, error('insufficient arguments'), end; -if nargout > 1, error('Too many output arguments Set'), end; +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{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; +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; +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 @@ -188,7 +188,7 @@ Fc.name = varargin{2}; Fc.STAT = varargin{3}; -if Fc.STAT=='T' & ~(any(strcmp(set_action,{'c+','c'}))) +if Fc.STAT=='T' && ~(any(strcmp(set_action,{'c+','c'}))) warning('enter T stat with contrast - here no check rank == 1'); end @@ -198,80 +198,80 @@ %- 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; + 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 + 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; + 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) @@ -283,7 +283,7 @@ 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; +if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end varargout = {sf_X0(Fc,sX)}; @@ -296,7 +296,7 @@ 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; +if ~spm_sp('isspc',sX), sX = spm_sp('set',sX); end varargout = {sf_X1o(Fc,sX)}; @@ -307,7 +307,7 @@ if nargin~=2, error('too few/many input arguments - need 2'), end if ~isstruct(varargin{2}), varargout={0}; -else, varargout = {sf_IsFcon(varargin{2})}; +else varargout = {sf_IsFcon(varargin{2})}; end @@ -319,11 +319,11 @@ 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 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; + sX = spm_sp('set',sX); end if ~sf_isempty_X1o(Fc) [trMV, trMVMV] = spm_SpUtil('trMV',sf_X1o(Fc,sX),V); @@ -332,18 +332,18 @@ trMVMV = 0; end if ~trMVMV, edf_tsp = 0; warning('edf_tsp = 0'), -else, edf_tsp = trMV^2/trMVMV; end; +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; + 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; +end @@ -511,11 +511,11 @@ 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) +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) + 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 @@ -531,7 +531,7 @@ if nargin < 3, error('Insufficient arguments'), end Fc1 = varargin{2}; sX = varargin{3}; -if nargin > 3, Fc2 = varargin{4}; else, Fc2 = []; end; +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; @@ -563,7 +563,7 @@ L1 = length(Fc1); if ~L1, warning('no contrast given to in'); if nargout == 2, varargout = {[] []}; - else, varargout = {[]}; end; + else varargout = {[]}; end; return; end for i=1:L1 @@ -634,7 +634,7 @@ idx = []; for i=1:L1 - if sf_isempty_X1o(Fc(i)) | sf_isnull(Fc(i),sX), idx = [idx i]; end + if sf_isempty_X1o(Fc(i)) || sf_isnull(Fc(i),sX), idx = [idx i]; end end if isempty(idx) varargout = {0}; @@ -666,12 +666,12 @@ 'name', '',... 'STAT', '',... 'c', [],... - 'X0', struct('ukX0',[]),... %!15/10 + 'X0', struct('ukX0',[]),... 'iX0', [],... - 'X1o', struct('ukX1o',[]),... %!15/10 + 'X1o', struct('ukX1o',[]),... 'eidf', [],... 'Vcon', [],... - 'Vspm', [] ); + 'Vspm', []); %======================================================================= % used internally. Minimum contrast structure @@ -682,9 +682,8 @@ 'name', '',... 'STAT', '',... 'c', [],... - 'X0', [],... - 'X1o', []... - ); + 'X0', [],... + 'X1o', []); %======================================================================= % yes_no = spm_FcUtil('IsFcon',Fc) @@ -727,7 +726,7 @@ if b ~= isempty(Fc.c), Fc.c, Fc.X1o.ukX1o, error('Contrast internally not consistent'); end -else, +else b = isempty(Fc.X1o); %- consistency check if b ~= isempty(Fc.c), @@ -741,7 +740,7 @@ if sf_ver(Fc) > 1, b = spm_sp('ox',sX)*Fc.X1o.ukX1o; -else, +else b = Fc.X1o; end @@ -752,7 +751,7 @@ if sf_ver(Fc) > 1, b = spm_sp('ox',sX)*Fc.X0.ukX0; -else, +else b = Fc.X0; end @@ -763,7 +762,7 @@ if sf_ver(Fc) > 1, b = isempty(Fc.X0.ukX0); -else, +else b = isempty(Fc.X0); end @@ -789,7 +788,7 @@ %-**** 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, +else hsqr = spm_sp('ox',spm_sp('set',Fc.X1o))'*spm_sp('x',sX); end %======================================================================= @@ -845,7 +844,7 @@ %- Fc1.STAT, 'c',c,sX); %======================================================================= -function b = sf_Rortho(Fc1,sX,Fc2); +function b = sf_Rortho(Fc1,sX,Fc2) if isempty(Fc2) if length(Fc1) <= 1, b = 0; @@ -881,13 +880,10 @@ 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; - - - +if rank(c) > 1 || any(any(c'*c < 0)), boul = 0; end; %======================================================================= -function [idxFc2, idxFc1] = sf_in(Fc1, sX, Fc2); +function [idxFc2, idxFc1] = sf_in(Fc1, sX, Fc2) L2 = length(Fc2); L1 = length(Fc1); @@ -897,14 +893,14 @@ %- 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, + else c1 = Fc1(j).c; end sc1 = spm_sp('Set',c1); S = Fc1(j).STAT; - boul = 0; i = 1; - for i =1:L2, + 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)); @@ -912,14 +908,14 @@ %- 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' + 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; + if boul, idxFc1 = [idxFc1 j]; idxFc2 = [idxFc2 i]; end + end end end %- for j=1:L1 diff --git a/spm_Fcdf.m b/spm_Fcdf.m index e34b4bb..7029bfb 100644 --- a/spm_Fcdf.m +++ b/spm_Fcdf.m @@ -9,12 +9,12 @@ % v - Shape parameter 1 / numerator degrees of freedom (v>0) % w - Shape parameter 2 / denominator degrees of freedom (w>0) % F - CDF of F-distribution with [v,w] degrees of freedom at points x -%_______________________________________________________________________ +%__________________________________________________________________________ % % spm_Fcdf implements the Cumulative Distribution Function of the F-distribution. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The CDF F(x) of the F distribution with degrees of freedom v & w, % defined for positive integer degrees of freedom v & w, is the % probability that a realisation of an F random variable X has value @@ -22,7 +22,7 @@ % for v>0 & w>0, and for x in [0,Inf) (See Evans et al., Ch16). % % Variate relationships: (Evans et al., Ch16 & 37) -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The square of a Student's t variate with w degrees of freedom is % distributed as an F-distribution with [1,w] degrees of freedom. % @@ -31,7 +31,7 @@ % w/2 & v/2. % % Algorithm: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Using the relationship with the Beta distribution: The CDF of the % F-distribution with v,w degrees of freedom is related to the % incomplete beta function by: @@ -41,11 +41,11 @@ % easily verified by substituting for w/(w+v*x^2) in the integral of the % incomplete beta function. % -% MatLab's implementation of the incomplete beta function is used. +% MATLAB's implementation of the incomplete beta function is used. % % % References: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Evans M, Hastings N, Peacock B (1993) % "Statistical Distributions" % 2nd Ed. Wiley, New York @@ -59,14 +59,14 @@ % Cambridge % %__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% Copyright (C) 1992-2011 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_Fcdf.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_Fcdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Format arguments, note & check sizes -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<2, error('Insufficient arguments'), end %-Unpack degrees of freedom v & w from single df parameter (v) @@ -88,23 +88,25 @@ %-Check argument sizes ad = [ndims(x);ndims(v);ndims(w)]; rd = max(ad); -as = [ [size(x),ones(1,rd-ad(1))];... - [size(v),ones(1,rd-ad(2))];... - [size(w),ones(1,rd-ad(3))] ]; +as = [[size(x),ones(1,rd-ad(1))];... + [size(v),ones(1,rd-ad(2))];... + [size(w),ones(1,rd-ad(3))]]; rs = max(as); xa = prod(as,2)>1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) error('non-scalar args must match in size'), end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros F = zeros(rs); %-Only defined for strictly positive v & w. Return NaN if undefined. md = ( ones(size(x)) & v>0 & w>0 ); -if any(~md(:)), F(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + F(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-Non-zero where defined and x>0 Q = find( md & x>0 ); diff --git a/spm_Fpdf.m b/spm_Fpdf.m index 64b4a90..fea2578 100644 --- a/spm_Fpdf.m +++ b/spm_Fpdf.m @@ -9,12 +9,12 @@ % v - Shape parameter 1 / numerator degrees of freedom (v>0) % w - Shape parameter 2 / denominator degrees of freedom (w>0) % f - PDF of F-distribution with [v,w] degrees of freedom at points x -%_______________________________________________________________________ +%__________________________________________________________________________ % % spm_Fpdf implements the Probability Density Function of the F-distribution. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The PDF of the F-distribution with degrees of freedom v & w, defined % for positive integer degrees of freedom v>0 & w>0, and for x in % [0,Inf) by: (See Evans et al., Ch16) @@ -24,7 +24,7 @@ % gamma(v/2)*gamma(w/2) * (1+(v/w)x)^((v+w)/2) % % Variate relationships: (Evans et al., Ch16 & 37) -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The square of a Student's t variate with w degrees of freedom is % distributed as an F-distribution with [1,w] degrees of freedom. % @@ -33,12 +33,12 @@ % w/2 & v/2. % % Algorithm: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Direct computation using the beta function for % gamma(v/2)*gamma(w/2) / gamma((v+w)/2) = beta(v/2,w/2) % % References: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Evans M, Hastings N, Peacock B (1993) % "Statistical Distributions" % 2nd Ed. Wiley, New York @@ -51,15 +51,15 @@ % "Numerical Recipes in C" % Cambridge % -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +%__________________________________________________________________________ +% Copyright (C) 1994-2011 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_Fpdf.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_Fpdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Format arguments, note & check sizes -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<2, error('Insufficient arguments'), end %-Unpack degrees of freedom v & w from single df parameter (v) @@ -81,23 +81,26 @@ %-Check argument sizes ad = [ndims(x);ndims(v);ndims(w)]; rd = max(ad); -as = [ [size(x),ones(1,rd-ad(1))];... - [size(v),ones(1,rd-ad(2))];... - [size(w),ones(1,rd-ad(3))] ]; +as = [[size(x),ones(1,rd-ad(1))];... + [size(v),ones(1,rd-ad(2))];... + [size(w),ones(1,rd-ad(3))]]; rs = max(as); xa = prod(as,2)>1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) - error('non-scalar args must match in size'), end +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) + error('non-scalar args must match in size'); +end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros f = zeros(rs); %-Only defined for strictly positive v & w. Return NaN if undefined. md = ( ones(size(x)) & v>0 & w>0 ); -if any(~md(:)), f(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + f(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-Non-zero where defined and x>0 Q = find( md & x>0 ); diff --git a/spm_Gcdf.m b/spm_Gcdf.m index c5afbf7..c7b37da 100644 --- a/spm_Gcdf.m +++ b/spm_Gcdf.m @@ -11,7 +11,7 @@ % spm_Gcdf implements the Cumulative Distribution of the Gamma-distribution. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The CDF F(x) of the Gamma distribution with shape parameter h and % scale l is the probability that a realisation of a Gamma random % variable X has value less than x F(x)=Pr{X1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) - error('non-scalar args must match in size'), end +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) + error('non-scalar args must match in size'); +end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros F = zeros(rs); %-Only defined for strictly positive h & l. Return NaN if undefined. md = ( ones(size(x)) & h>0 & l>0 ); -if any(~md(:)), F(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + F(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-Non-zero where defined and x>0 Q = find( md & x>0 ); diff --git a/spm_Gpdf.m b/spm_Gpdf.m index 9a7c848..309fd9f 100644 --- a/spm_Gpdf.m +++ b/spm_Gpdf.m @@ -1,29 +1,29 @@ function f = spm_Gpdf(x,h,l) % Probability Density Function (PDF) of Gamma distribution -% FORMAT f = spm_Gpdf(g,h,l) +% FORMAT f = spm_Gpdf(x,h,l) % % x - Gamma-variate (Gamma has range [0,Inf) ) % h - Shape parameter (h>0) % l - Scale parameter (l>0) % f - PDF of Gamma-distribution with shape & scale parameters h & l -%_______________________________________________________________________ +%__________________________________________________________________________ % % spm_Gpdf implements the Probability Density Function of the Gamma % distribution. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The PDF of the Gamma distribution with shape parameter h and scale l % is defined for h>0 & l>0 and for x in [0,Inf) by: (See Evans et al., % Ch18, but note that this reference uses the alternative % parameterisation of the Gamma with scale parameter c=1/l) % % l^h * x^(h-1) exp(-lx) -% f(x) = --------------------- -% gamma(h) +% f(x) = ---------------------- +% gamma(h) % % Variate relationships: (Evans et al., Ch18 & Ch8) -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % For natural (strictly +ve integer) shape h this is an Erlang distribution. % % The Standard Gamma distribution has a single parameter, the shape h. @@ -33,11 +33,11 @@ % to the Gamma distribution with scale parameter 1/2 and shape parameter v/2. % % Algorithm: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Direct computation using logs to avoid roundoff errors. % % References: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Evans M, Hastings N, Peacock B (1993) % "Statistical Distributions" % 2nd Ed. Wiley, New York @@ -49,36 +49,39 @@ % Press WH, Teukolsky SA, Vetterling AT, Flannery BP (1992) % "Numerical Recipes in C" % Cambridge -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +%__________________________________________________________________________ +% Copyright (C) 1993-2011 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_Gpdf.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_Gpdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Format arguments, note & check sizes -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<3, error('Insufficient arguments'), end ad = [ndims(x);ndims(h);ndims(l)]; rd = max(ad); -as = [ [size(x),ones(1,rd-ad(1))];... - [size(h),ones(1,rd-ad(2))];... - [size(l),ones(1,rd-ad(3))] ]; +as = [[size(x),ones(1,rd-ad(1))];... + [size(h),ones(1,rd-ad(2))];... + [size(l),ones(1,rd-ad(3))]]; rs = max(as); xa = prod(as,2)>1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) - error('non-scalar args must match in size'), end +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) + error('non-scalar args must match in size'); +end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros f = zeros(rs); %-Only defined for strictly positive h & l. Return NaN if undefined. md = ( ones(size(x)) & h>0 & l>0 ); -if any(~md(:)), f(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + f(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-Degenerate cases at x==0: h<1 => f=Inf; h==1 => f=l; h>1 => f=0 ml = ( md & x==0 & h<1 ); diff --git a/spm_Icdf.m b/spm_Icdf.m index 7ae699e..f335286 100644 --- a/spm_Icdf.m +++ b/spm_Icdf.m @@ -6,13 +6,13 @@ % n - Binomial n % p - Binomial p [Defaults to 0.5] % F - CDF -%_______________________________________________________________________ +%__________________________________________________________________________ % % spm_Icdf returns the Cumulative Distribution Function for the % Binomial family of distributions. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The Bin(n,p) distribution is the distribution of the number of % successes from n identical independent Bernoulli trials each with % success probability p. If random variable X is the number of @@ -31,7 +31,7 @@ % where nCx is the Binomial coefficient "n-choose-x", given by n!/(x!(n-x)!) % % Normal approximation: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % For (npq>5 & 0.1<=p<=0.9) | min(np,nq)>10 | npq>25 the Normal % approximation to the Binomial may be used: % X~Bin(n,p), X~:~N(np,npq) ( ~:~ -> approx. distributed as) @@ -41,7 +41,7 @@ % \Phi(x) = 0.5+0.5*erf(x/sqrt(2)) % % Algorithm: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % F(x), the CDF of the Binomial distribution, for X~Bin(n,p), is related % to the incomplete beta function, by: % @@ -51,7 +51,7 @@ % further details. % % References: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Evans M, Hastings N, Peacock B (1993) % "Statistical Distributions" % 2nd Ed. Wiley, New York @@ -64,16 +64,16 @@ % "Numerical Recipes in C" % Cambridge % -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +%__________________________________________________________________________ +% Copyright (C) 1999-2011 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_Icdf.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_Icdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Format arguments, note & check sizes -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<3, p=0.5; end if nargin<2, error('Insufficient arguments'), end ad = [ndims(x);ndims(n);ndims(p)]; @@ -83,18 +83,21 @@ [size(p),ones(1,rd-ad(3))] ]; rs = max(as); xa = prod(as,2)>1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) - error('non-scalar args must match in size'), end +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) + error('non-scalar args must match in size'); +end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros F = zeros(rs); %-Only defined for whole n, and for p in [0,1]. Return NaN if undefined. md = ( ones(size(x)) & n==floor(n) & n>=0 & p>=0 & p<=1 ); -if any(~md(:)), F(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + F(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-F is 1 where x>=n, or (p=0 & x>=0) (where betainc involves log of zero) m1 = ( x>=n | (p==0 & x>=0) ); diff --git a/spm_Ipdf.m b/spm_Ipdf.m index efbfaf4..5457a31 100644 --- a/spm_Ipdf.m +++ b/spm_Ipdf.m @@ -6,13 +6,13 @@ % n - Binomial n % p - Binomial p [Defaults to 0.5] % f - PDF -%_______________________________________________________________________ +%__________________________________________________________________________ % % spm_Ipdf returns the Probability (Distribution) Function (PDF) for % the Binomial family of distributions. % % Definition: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % The Bin(n,p) distribution is the distribution of the number of % successes from n identical independent Bernoulli trials each with % success probability p. If random variable X is the number of @@ -27,7 +27,7 @@ % where nCx is the Binomial coefficient "n-choose-x", given by n!/(x!(n-x)!). % % Algorithm: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % For vary small n, nCx can be computed naively as the ratio of % factorials, using gamma(n+1) to return n!. For moderately sized n, n! % (& x! &/or (n-x)!) become very large, and naive computation isn't @@ -49,7 +49,7 @@ % of n & x. See Press et al., Sec6.1 for further details. % % References: -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % Evans M, Hastings N, Peacock B (1993) % "Statistical Distributions" % 2nd Ed. Wiley, New York @@ -62,37 +62,39 @@ % "Numerical Recipes in C" % Cambridge % -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +%__________________________________________________________________________ +% Copyright (C) 1999-2011 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_Ipdf.m 1143 2008-02-07 19:33:33Z spm $ - +% $Id: spm_Ipdf.m 4182 2011-02-01 12:29:09Z guillaume $ %-Format arguments, note & check sizes -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<3, p=0.5; end if nargin<2, error('Insufficient arguments'), end ad = [ndims(x);ndims(n);ndims(p)]; rd = max(ad); -as = [ [size(x),ones(1,rd-ad(1))];... - [size(n),ones(1,rd-ad(2))];... - [size(p),ones(1,rd-ad(3))] ]; +as = [[size(x),ones(1,rd-ad(1))];... + [size(n),ones(1,rd-ad(2))];... + [size(p),ones(1,rd-ad(3))]]; rs = max(as); xa = prod(as,2)>1; -if sum(xa)>1 & any(any(diff(as(xa,:)),1)) - error('non-scalar args must match in size'), end +if sum(xa)>1 && any(any(diff(as(xa,:)),1)) + error('non-scalar args must match in size'); +end %-Computation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Initialise result to zeros f = zeros(rs); %-Only defined for whole n, and for p in [0,1]. Return NaN if undefined. md = ( ones(size(x)) & n==floor(n) & n>=0 & p>=0 & p<=1 ); -if any(~md(:)), f(~md) = NaN; - warning('Returning NaN for out of range arguments'), end +if any(~md(:)) + f(~md) = NaN; + warning('Returning NaN for out of range arguments'); +end %-Non-zero only where defined and x is whole with 0<=x<=n Q = find( md & x==floor(x) & n>=x & x>=0 ); @@ -106,23 +108,23 @@ f(Q) = f(Q).* p(Qp).^x(Qx) .* (1-p(Qp)).^(n(Qn)-x(Qx)); %-Return -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- return -%======================================================================= +%========================================================================== %-Direct computation method: (For interest) -%======================================================================= +%========================================================================== % The following cunning direct computation is faster than using log % gammas, but is rather difficult to vectorise. %q=1-p; %if r